Example #1
0
/* Test if the peripheral is IEEE 1284 compliant.
 * return values are:
 *   0 - handshake failed; peripheral is not compliant (or none present)
 *   1 - handshake OK; IEEE1284 peripheral present but no data available
 *   2 - handshake OK; IEEE1284 peripheral and data available
 */
int parport_ieee1284_nibble_mode_ok(struct parport *port, unsigned char mode) 
{
	/* make sure it's a valid state, set nStrobe & nAutoFeed high */
	parport_write_control(port, (parport_read_control(port) \
		& ~1 ) & ~2);
	udelay(1);
	parport_write_data(port, mode);
	udelay(1);
	/* nSelectIn high, nAutoFd low */
	parport_write_control(port, (parport_read_control(port) & ~8) | 2);
	if (parport_wait_peripheral(port, 0x78, 0x38)) {
		parport_write_control(port, 
				      (parport_read_control(port) & ~2) | 8);
		return 0; 
	}
	/* nStrobe low */
	parport_write_control(port, parport_read_control(port) | 1);
	udelay(1);				     /* Strobe wait */
	/* nStrobe high, nAutoFeed low, last step before transferring 
	 *  reverse data */
	parport_write_control(port, (parport_read_control(port) \
		& ~1) & ~2);
	udelay(1);
	/* Data available? */
	return (parport_wait_peripheral(port, 0x20, 0))?1:2;
}
Example #2
0
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
				     | PARPORT_STATUS_PAPEROUT
				     | PARPORT_STATUS_ACK,
				     PARPORT_STATUS_ERROR
				     | PARPORT_STATUS_SELECT
				     | PARPORT_STATUS_PAPEROUT)) {
		/* Timeout */
		parport_frob_control (port,
				      PARPORT_CONTROL_SELECT
				      | PARPORT_CONTROL_AUTOFD,
				      PARPORT_CONTROL_SELECT);
		DPRINTK (KERN_DEBUG
			 "%s: Peripheral not IEEE1284 compliant (0x%02X)\n",
			 port->name, parport_read_status (port));
		port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
		return -1; /* Not IEEE1284 compliant */
	}

	/* Event 3: Set nStrobe low */
	parport_frob_control (port,
			      PARPORT_CONTROL_STROBE,
			      PARPORT_CONTROL_STROBE);

	/* Event 4: Set nStrobe and nAutoFd high */
	udelay (5);
	parport_frob_control (port,
			      PARPORT_CONTROL_STROBE
			      | PARPORT_CONTROL_AUTOFD,
			      0);

	/* Event 6: nAck goes high */
	if (parport_wait_peripheral (port,
				     PARPORT_STATUS_ACK,
				     PARPORT_STATUS_ACK)) {
		/* This shouldn't really happen with a compliant device. */
		DPRINTK (KERN_DEBUG
			 "%s: Mode 0x%02x not supported? (0x%02x)\n",
			 port->name, mode, port->ops->read_status (port));
		parport_ieee1284_terminate (port);
		return 1;
	}

	xflag = parport_read_status (port) & PARPORT_STATUS_SELECT;

	/* xflag should be high for all modes other than nibble (0). */
	if (mode && !xflag) {
		/* Mode not supported. */
		DPRINTK (KERN_DEBUG "%s: Mode 0x%02x rejected by peripheral\n",
			 port->name, mode);
		parport_ieee1284_terminate (port);
		return 1;
	}

	/* More to do if we've requested extensibility link. */
	if (mode & IEEE1284_EXT_LINK) {
		m = mode & 0x7f;
		udelay (1);
		parport_write_data (port, m);
		udelay (1);

		/* Event 51: Set nStrobe low */
		parport_frob_control (port,
				      PARPORT_CONTROL_STROBE,
				      PARPORT_CONTROL_STROBE);

		/* Event 52: nAck goes low */
		if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) {
			/* This peripheral is _very_ slow. */
			DPRINTK (KERN_DEBUG
				 "%s: Event 52 didn't happen\n",
				 port->name);
			parport_ieee1284_terminate (port);
			return 1;
		}

		/* Event 53: Set nStrobe high */
		parport_frob_control (port,
				      PARPORT_CONTROL_STROBE,
				      0);

		/* Event 55: nAck goes high */
		if (parport_wait_peripheral (port,
					     PARPORT_STATUS_ACK,
					     PARPORT_STATUS_ACK)) {
			/* This shouldn't really happen with a compliant
			 * device. */
			DPRINTK (KERN_DEBUG
				 "%s: Mode 0x%02x not supported? (0x%02x)\n",
				 port->name, mode,
				 port->ops->read_status (port));
			parport_ieee1284_terminate (port);
			return 1;
		}

		/* Event 54: Peripheral sets XFlag to reflect support */
		xflag = parport_read_status (port) & PARPORT_STATUS_SELECT;

		/* xflag should be high. */
		if (!xflag) {
			/* Extended mode not supported. */
			DPRINTK (KERN_DEBUG "%s: Extended mode 0x%02x not "
				 "supported\n", port->name, mode);
			parport_ieee1284_terminate (port);
			return 1;
		}

		/* Any further setup is left to the caller. */
	}

	/* Mode is supported */
	DPRINTK (KERN_DEBUG "%s: In mode 0x%02x\n", port->name, mode);
	port->ieee1284.mode = mode;

	/* But ECP is special */
	if (!(mode & IEEE1284_EXT_LINK) && (m & IEEE1284_MODE_ECP)) {
		port->ieee1284.phase = IEEE1284_PH_ECP_SETUP;

		/* Event 30: Set nAutoFd low */
		parport_frob_control (port,
				      PARPORT_CONTROL_AUTOFD,
				      PARPORT_CONTROL_AUTOFD);

		/* Event 31: PError goes high. */
		r = parport_wait_peripheral (port,
					     PARPORT_STATUS_PAPEROUT,
					     PARPORT_STATUS_PAPEROUT);
		if (r) {
			DPRINTK (KERN_INFO "%s: Timeout at event 31\n",
				port->name);
		}

		port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
		DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n",
			 port->name);
	} else switch (mode) {
	case IEEE1284_MODE_NIBBLE:
	case IEEE1284_MODE_BYTE:
		port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
		break;
	default:
		port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
	}


	return 0;
#endif /* IEEE1284 support */
}
Example #3
0
/* 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);
}		
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;

	
	if (port->ieee1284.mode == mode)
		return 0;

	
	if ((port->ieee1284.mode & ~IEEE1284_ADDR) == (mode & ~IEEE1284_ADDR)){
		port->ieee1284.mode = mode;
		return 0;
	}

	
	if (port->ieee1284.mode != IEEE1284_MODE_COMPAT)
		parport_ieee1284_terminate (port);

	if (mode == IEEE1284_MODE_COMPAT)
		
		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; 
	}

	if (mode & IEEE1284_EXT_LINK)
		m = 1<<7; 

	port->ieee1284.phase = IEEE1284_PH_NEGOTIATION;

	
	parport_frob_control (port,
			      PARPORT_CONTROL_STROBE
			      | PARPORT_CONTROL_AUTOFD
			      | PARPORT_CONTROL_SELECT,
			      PARPORT_CONTROL_SELECT);
	udelay(1);

	
	parport_data_forward (port);
	parport_write_data (port, m);
	udelay (400); 

	
	parport_frob_control (port,
			      PARPORT_CONTROL_SELECT
			      | PARPORT_CONTROL_AUTOFD,
			      PARPORT_CONTROL_AUTOFD);

	
	if (parport_wait_peripheral (port,
				     PARPORT_STATUS_ERROR
				     | PARPORT_STATUS_SELECT
				     | PARPORT_STATUS_PAPEROUT
				     | PARPORT_STATUS_ACK,
				     PARPORT_STATUS_ERROR
				     | PARPORT_STATUS_SELECT
				     | PARPORT_STATUS_PAPEROUT)) {
		
		parport_frob_control (port,
				      PARPORT_CONTROL_SELECT
				      | PARPORT_CONTROL_AUTOFD,
				      PARPORT_CONTROL_SELECT);
		DPRINTK (KERN_DEBUG
			 "%s: Peripheral not IEEE1284 compliant (0x%02X)\n",
			 port->name, parport_read_status (port));
		port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
		return -1; 
	}

	
	parport_frob_control (port,
			      PARPORT_CONTROL_STROBE,
			      PARPORT_CONTROL_STROBE);

	
	udelay (5);
	parport_frob_control (port,
			      PARPORT_CONTROL_STROBE
			      | PARPORT_CONTROL_AUTOFD,
			      0);

	
	if (parport_wait_peripheral (port,
				     PARPORT_STATUS_ACK,
				     PARPORT_STATUS_ACK)) {
		
		DPRINTK (KERN_DEBUG
			 "%s: Mode 0x%02x not supported? (0x%02x)\n",
			 port->name, mode, port->ops->read_status (port));
		parport_ieee1284_terminate (port);
		return 1;
	}

	xflag = parport_read_status (port) & PARPORT_STATUS_SELECT;

	
	if (mode && !xflag) {
		
		DPRINTK (KERN_DEBUG "%s: Mode 0x%02x rejected by peripheral\n",
			 port->name, mode);
		parport_ieee1284_terminate (port);
		return 1;
	}

	
	if (mode & IEEE1284_EXT_LINK) {
		m = mode & 0x7f;
		udelay (1);
		parport_write_data (port, m);
		udelay (1);

		
		parport_frob_control (port,
				      PARPORT_CONTROL_STROBE,
				      PARPORT_CONTROL_STROBE);

		
		if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) {
			
			DPRINTK (KERN_DEBUG
				 "%s: Event 52 didn't happen\n",
				 port->name);
			parport_ieee1284_terminate (port);
			return 1;
		}

		
		parport_frob_control (port,
				      PARPORT_CONTROL_STROBE,
				      0);

		
		if (parport_wait_peripheral (port,
					     PARPORT_STATUS_ACK,
					     PARPORT_STATUS_ACK)) {
			DPRINTK (KERN_DEBUG
				 "%s: Mode 0x%02x not supported? (0x%02x)\n",
				 port->name, mode,
				 port->ops->read_status (port));
			parport_ieee1284_terminate (port);
			return 1;
		}

		
		xflag = parport_read_status (port) & PARPORT_STATUS_SELECT;

		
		if (!xflag) {
			
			DPRINTK (KERN_DEBUG "%s: Extended mode 0x%02x not "
				 "supported\n", port->name, mode);
			parport_ieee1284_terminate (port);
			return 1;
		}

		
	}

	
	DPRINTK (KERN_DEBUG "%s: In mode 0x%02x\n", port->name, mode);
	port->ieee1284.mode = mode;

	
	if (!(mode & IEEE1284_EXT_LINK) && (m & IEEE1284_MODE_ECP)) {
		port->ieee1284.phase = IEEE1284_PH_ECP_SETUP;

		
		parport_frob_control (port,
				      PARPORT_CONTROL_AUTOFD,
				      PARPORT_CONTROL_AUTOFD);

		
		r = parport_wait_peripheral (port,
					     PARPORT_STATUS_PAPEROUT,
					     PARPORT_STATUS_PAPEROUT);
		if (r) {
			DPRINTK (KERN_INFO "%s: Timeout at event 31\n",
				port->name);
		}

		port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
		DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n",
			 port->name);
	} else switch (mode) {
	case IEEE1284_MODE_NIBBLE:
	case IEEE1284_MODE_BYTE:
		port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
		break;
	default:
		port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
	}


	return 0;
#endif 
}
static void parport_ieee1284_terminate (struct parport *port)
{
	int r;
	port = port->physport;

	
	switch (port->ieee1284.mode) {
	case IEEE1284_MODE_EPP:
	case IEEE1284_MODE_EPPSL:
	case IEEE1284_MODE_EPPSWE:
		

		
		parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
		udelay (50);

		
		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:
		
		if (port->ieee1284.phase != IEEE1284_PH_FWD_IDLE) {
			
			parport_frob_control (port,
					      PARPORT_CONTROL_INIT
					      | PARPORT_CONTROL_AUTOFD,
					      PARPORT_CONTROL_INIT
					      | PARPORT_CONTROL_AUTOFD);

			
			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;
		}

		

	default:
		

		
		parport_frob_control (port,
				      PARPORT_CONTROL_SELECT
				      | PARPORT_CONTROL_AUTOFD,
				      PARPORT_CONTROL_SELECT);

		
		r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0);
		if (r)
			DPRINTK (KERN_INFO "%s: Timeout at event 24\n",
				 port->name);

		
		parport_frob_control (port,
				      PARPORT_CONTROL_AUTOFD,
				      PARPORT_CONTROL_AUTOFD);

		
		r = parport_wait_peripheral (port,
					     PARPORT_STATUS_ACK, 
					     PARPORT_STATUS_ACK);
		if (r)
			DPRINTK (KERN_INFO "%s: Timeout at event 27\n",
				 port->name);

		
		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);
}