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

📄 ieee1284.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: parport_ieee1284.c,v 1.4 1997/10/19 21:37:21 philip Exp $ * IEEE-1284 implementation for parport. * * Authors: Phil Blundell <Philip.Blundell@pobox.com> *          Carsten Gross <carsten@sol.wohnheim.uni-ulm.de> *	    Jose Renau <renau@acm.org> *          Tim Waugh <tim@cyberelk.demon.co.uk> (largely rewritten) * * This file is responsible for IEEE 1284 negotiation, and for handing * read/write requests to low-level drivers. * * Any part of this program may be used in documents licensed under * the GNU Free Documentation License, Version 1.1 or any later version * published by the Free Software Foundation. * * Various hacks, Fred Barnes <frmb2@ukc.ac.uk>, 04/2000 */#include <linux/config.h>#include <linux/threads.h>#include <linux/parport.h>#include <linux/delay.h>#include <linux/kernel.h>#include <linux/interrupt.h>#undef DEBUG /* undef me for production */#ifdef CONFIG_LP_CONSOLE#undef DEBUG /* Don't want a garbled console */#endif#ifdef DEBUG#define DPRINTK(stuff...) printk (stuff)#else#define DPRINTK(stuff...)#endif/* Make parport_wait_peripheral wake up. * It will be useful to call this from an interrupt handler. */void parport_ieee1284_wakeup (struct parport *port){	up (&port->physport->ieee1284.irq);}static struct parport *port_from_cookie[PARPORT_MAX];static void timeout_waiting_on_port (unsigned long cookie){	parport_ieee1284_wakeup (port_from_cookie[cookie % PARPORT_MAX]);}/** *	parport_wait_event - wait for an event on a parallel port *	@port: port to wait on *	@timeout: time to wait (in jiffies) * *	This function waits for up to @timeout jiffies for an *	interrupt to occur on a parallel port.  If the port timeout is *	set to zero, it returns immediately. * *	If an interrupt occurs before the timeout period elapses, this *	function returns one immediately.  If it times out, it returns *	a value greater than zero.  An error code less than zero *	indicates an error (most likely a pending signal), and the *	calling code should finish what it's doing as soon as it can. */int parport_wait_event (struct parport *port, signed long timeout){	int ret;	struct timer_list timer;	if (!port->physport->cad->timeout)		/* Zero timeout is special, and we can't down() the		   semaphore. */		return 1;	init_timer (&timer);	timer.expires = jiffies + timeout;	timer.function = timeout_waiting_on_port;	port_from_cookie[port->number % PARPORT_MAX] = port;	timer.data = port->number;	add_timer (&timer);	ret = down_interruptible (&port->physport->ieee1284.irq);	if (!del_timer (&timer) && !ret)		/* Timed out. */		ret = 1;	return ret;}/** *	parport_poll_peripheral - poll status lines *	@port: port to watch *	@mask: status lines to watch *	@result: desired values of chosen status lines *	@usec: timeout * *	This function busy-waits until the masked status lines have *	the desired values, or until the timeout period elapses.  The *	@mask and @result parameters are bitmasks, with the bits *	defined by the constants in parport.h: %PARPORT_STATUS_BUSY, *	and so on. * *	This function does not call schedule(); instead it busy-waits *	using udelay().  It currently has a resolution of 5usec. * *	If the status lines take on the desired values before the *	timeout period elapses, parport_poll_peripheral() returns zero *	immediately.  A zero return value greater than zero indicates *	a timeout.  An error code (less than zero) indicates an error, *	most likely a signal that arrived, and the caller should *	finish what it is doing as soon as possible.*/int parport_poll_peripheral(struct parport *port,			    unsigned char mask,			    unsigned char result,			    int usec){	/* Zero return code is success, >0 is timeout. */	int count = usec / 5 + 2;	int i;	unsigned char status;	for (i = 0; i < count; i++) {		status = parport_read_status (port);		if ((status & mask) == result)			return 0;		if (signal_pending (current))			return -EINTR;		if (current->need_resched)			break;		if (i >= 2)			udelay (5);	}	return 1;}/** *	parport_wait_peripheral - wait for status lines to change in 35ms *	@port: port to watch *	@mask: status lines to watch *	@result: desired values of chosen status lines * *	This function waits until the masked status lines have the *	desired values, or until 35ms have elapsed (see IEEE 1284-1994 *	page 24 to 25 for why this value in particular is hardcoded). *	The @mask and @result parameters are bitmasks, with the bits *	defined by the constants in parport.h: %PARPORT_STATUS_BUSY, *	and so on. * *	The port is polled quickly to start off with, in anticipation *	of a fast response from the peripheral.  This fast polling *	time is configurable (using /proc), and defaults to 500usec. *	If the timeout for this port (see parport_set_timeout()) is *	zero, the fast polling time is 35ms, and this function does *	not call schedule(). * *	If the timeout for this port is non-zero, after the fast *	polling fails it uses parport_wait_event() to wait for up to *	10ms, waking up if an interrupt occurs. */int parport_wait_peripheral(struct parport *port,			    unsigned char mask, 			    unsigned char result){	int ret;	int usec;	long deadline;	unsigned char status;	usec = port->physport->spintime; /* usecs of fast polling */	if (!port->physport->cad->timeout)		/* A zero timeout is "special": busy wait for the		   entire 35ms. */		usec = 35000;	/* Fast polling.	 *	 * This should be adjustable.	 * How about making a note (in the device structure) of how long	 * it takes, so we know for next time?	 */	ret = parport_poll_peripheral (port, mask, result, usec);	if (ret != 1)		return ret;	if (!port->physport->cad->timeout)		/* We may be in an interrupt handler, so we can't poll		 * slowly anyway. */		return 1;	/* 40ms of slow polling. */	deadline = jiffies + (HZ + 24) / 25;	while (time_before (jiffies, deadline)) {		int ret;		if (signal_pending (current))			return -EINTR;		/* Wait for 10ms (or until an interrupt occurs if		 * the handler is set) */		if ((ret = parport_wait_event (port, (HZ + 99) / 100)) < 0)			return ret;		status = parport_read_status (port);		if ((status & mask) == result)			return 0;		if (!ret) {			/* parport_wait_event didn't time out, but the			 * peripheral wasn't actually ready either.			 * Wait for another 10ms. */			__set_current_state (TASK_INTERRUPTIBLE);			schedule_timeout ((HZ+ 99) / 100);		}	}	return 1;}#ifdef CONFIG_PARPORT_1284/* Terminate a negotiated mode. */static void parport_ieee1284_terminate (struct parport *port){	int r;	port = port->physport;	/* EPP terminates differently. */	switch (port->ieee1284.mode) {	case IEEE1284_MODE_EPP:	case IEEE1284_MODE_EPPSL:	case IEEE1284_MODE_EPPSWE:		/* Terminate from EPP mode. */		/* Event 68: Set nInit low */		parport_frob_control (port, PARPORT_CONTROL_INIT, 0);		udelay (50);		/* Event 69: Set nInit high, nSelectIn low */		parport_frob_control (port,				      PARPORT_CONTROL_SELECT				      | PARPORT_CONTROL_INIT,				      PARPORT_CONTROL_SELECT				      | PARPORT_CONTROL_INIT);		break;	case IEEE1284_MODE_ECP:	case IEEE1284_MODE_ECPRLE:	case IEEE1284_MODE_ECPSWE:		/* In ECP we can only terminate from fwd idle phase. */		if (port->ieee1284.phase != IEEE1284_PH_FWD_IDLE) {			/* Event 47: Set nInit high */			parport_frob_control (port,					      PARPORT_CONTROL_INIT					      | PARPORT_CONTROL_AUTOFD,					      PARPORT_CONTROL_INIT					      | PARPORT_CONTROL_AUTOFD);			/* Event 49: PError goes high */			r = parport_wait_peripheral (port,						     PARPORT_STATUS_PAPEROUT,						     PARPORT_STATUS_PAPEROUT);			if (r)				DPRINTK (KERN_INFO "%s: Timeout at event 49\n",					 port->name);			parport_data_forward (port);			DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n",				 port->name);			port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;		}		/* fall-though.. */	default:		/* Terminate from all other modes. */		/* Event 22: Set nSelectIn low, nAutoFd high */		parport_frob_control (port,				      PARPORT_CONTROL_SELECT				      | PARPORT_CONTROL_AUTOFD,				      PARPORT_CONTROL_SELECT);		/* Event 24: nAck goes low */		r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0);		if (r)			DPRINTK (KERN_INFO "%s: Timeout at event 24\n",				 port->name);		/* Event 25: Set nAutoFd low */		parport_frob_control (port,				      PARPORT_CONTROL_AUTOFD,				      PARPORT_CONTROL_AUTOFD);		/* Event 27: nAck goes high */		r = parport_wait_peripheral (port,					     PARPORT_STATUS_ACK, 					     PARPORT_STATUS_ACK);		if (r)			DPRINTK (KERN_INFO "%s: Timeout at event 27\n",				 port->name);		/* Event 29: Set nAutoFd high */		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);	}	port->ieee1284.mode = IEEE1284_MODE_COMPAT;	port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;	DPRINTK (KERN_DEBUG "%s: In compatibility (forward idle) mode\n",		 port->name);}		#endif /* IEEE1284 support *//** *	parport_negotiate - negotiate an IEEE 1284 mode *	@port: port to use *	@mode: mode to negotiate to * *	Use this to negotiate to a particular IEEE 1284 transfer mode. *	The @mode parameter should be one of the constants in *	parport.h starting %IEEE1284_MODE_xxx. * *	The return value is 0 if the peripheral has accepted the *	negotiation to the mode specified, -1 if the peripheral is not *	IEEE 1284 compliant (or not present), or 1 if the peripheral *	has rejected the negotiation. */int parport_negotiate (struct parport *port, int mode){#ifndef CONFIG_PARPORT_1284	if (mode == IEEE1284_MODE_COMPAT)		return 0;	printk (KERN_ERR "parport: IEEE1284 not supported in this kernel\n");	return -1;#else	int m = mode & ~IEEE1284_ADDR;	int r;	unsigned char xflag;	port = port->physport;	/* Is there anything to do? */	if (port->ieee1284.mode == mode)		return 0;	/* Is the difference just an address-or-not bit? */	if ((port->ieee1284.mode & ~IEEE1284_ADDR) == (mode & ~IEEE1284_ADDR)){		port->ieee1284.mode = mode;		return 0;	}	/* Go to compability forward idle mode */	if (port->ieee1284.mode != IEEE1284_MODE_COMPAT)		parport_ieee1284_terminate (port);	if (mode == IEEE1284_MODE_COMPAT)		/* Compatibility mode: no negotiation. */		return 0; 	switch (mode) {	case IEEE1284_MODE_ECPSWE:		m = IEEE1284_MODE_ECP;		break;	case IEEE1284_MODE_EPPSL:	case IEEE1284_MODE_EPPSWE:		m = IEEE1284_MODE_EPP;		break;	case IEEE1284_MODE_BECP:		return -ENOSYS; /* FIXME (implement BECP) */	}	if (mode & IEEE1284_EXT_LINK)		m = 1<<7; /* request extensibility link */	port->ieee1284.phase = IEEE1284_PH_NEGOTIATION;	/* Start off with nStrobe and nAutoFd high, and nSelectIn low */	parport_frob_control (port,			      PARPORT_CONTROL_STROBE			      | PARPORT_CONTROL_AUTOFD			      | PARPORT_CONTROL_SELECT,			      PARPORT_CONTROL_SELECT);	udelay(1);	/* Event 0: Set data */	parport_data_forward (port);	parport_write_data (port, m);	udelay (400); /* Shouldn't need to wait this long. */	/* Event 1: Set nSelectIn high, nAutoFd low */	parport_frob_control (port,			      PARPORT_CONTROL_SELECT			      | PARPORT_CONTROL_AUTOFD,			      PARPORT_CONTROL_AUTOFD);	/* Event 2: PError, Select, nFault go high, nAck goes low */	if (parport_wait_peripheral (port,				     PARPORT_STATUS_ERROR				     | PARPORT_STATUS_SELECT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -