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

📄 ppuser.c

📁 simple MIPS EJTAG u-boot loader
💻 C
字号:
/*****************************************************************************//* *      ppuser.c  -- Parport access via Linux PPUSER device. * *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch) * *      This program is free software; you can redistribute it and/or modify *      it under the terms of the GNU General Public License as published by *      the Free Software Foundation; either version 2 of the License, or *      (at your option) any later version. * *      This program is distributed in the hope that it will be useful, *      but WITHOUT ANY WARRANTY; without even the implied warranty of *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *      GNU General Public License for more details. * *      You should have received a copy of the GNU General Public License *      along with this program; if not, write to the Free Software *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *  Please note that the GPL allows you to use the driver, NOT the radio. *  In order to use the radio, you need a license from the communications *  authority of your country. * *//*****************************************************************************/#include <sys/ioctl.h>#include <unistd.h>#include "parport.h"#include "ppuser.h"/* ---------------------------------------------------------------------- */int pp_user_fd = -1;/* ---------------------------------------------------------------------- */void parport_user_exit(void){	if (pp_user_fd != -1) {		ioctl(pp_user_fd, PPRELEASE, 0);		close(pp_user_fd);	}	pp_user_fd = -1;}/* ---------------------------------------------------------------------- */unsigned char parport_user_read_data(void){	unsigned char r;		ioctl(pp_user_fd, PPRDATA, &r);	return r;}void parport_user_write_data(unsigned char d){	ioctl(pp_user_fd, PPWDATA, &d);}unsigned char parport_user_read_status(void){	unsigned char r;		ioctl(pp_user_fd, PPRSTATUS, &r);	return r;}unsigned char parport_user_read_control(void){	unsigned char r;		ioctl(pp_user_fd, PPRCONTROL, &r);	return r;}void parport_user_write_control(unsigned char d){	ioctl(pp_user_fd, PPWCONTROL, &d);}void parport_user_frob_control(unsigned char mask, unsigned char val){	unsigned char d;		ioctl(pp_user_fd, PPRCONTROL, &d);	d = (d & (~mask)) ^ val;	ioctl(pp_user_fd, PPWCONTROL, &d);}/* ---------------------------------------------------------------------- */unsigned parport_user_epp_write_data(const void *buf, unsigned sz){	unsigned char *bp = (unsigned char *)buf;	unsigned ret = 0;	unsigned tmo;	unsigned char d;	d = LPTCTRL_PROGRAM | LPTCTRL_WRITE;	ioctl(pp_user_fd, PPWCONTROL, &d);	for (; sz > 0; sz--, bp++) {		ioctl(pp_user_fd, PPWDATA, bp);		for (tmo = 0; ; tmo++) {			ioctl(pp_user_fd, PPRSTATUS, &d);			if (d & LPTSTAT_WAIT)				break;			if (tmo > 1000)				return ret;		}		d = LPTCTRL_PROGRAM | LPTCTRL_WRITE | LPTCTRL_DATASTB;		ioctl(pp_user_fd, PPWCONTROL, &d);		for (tmo = 0; ; tmo++) {			ioctl(pp_user_fd, PPRSTATUS, &d);			if (!(d & LPTSTAT_WAIT))				break;			if (tmo > 1000)				return ret;		}		d = LPTCTRL_PROGRAM | LPTCTRL_WRITE;		ioctl(pp_user_fd, PPWCONTROL, &d);		ret++;	}	return ret;}unsigned parport_user_epp_read_data(void *buf, unsigned sz){	unsigned char *bp = (unsigned char *)buf;	unsigned ret = 0;	unsigned tmo;	unsigned char d;	d = LPTCTRL_PROGRAM | LPTCTRL_DIRECTION;	ioctl(pp_user_fd, PPWCONTROL, &d);	for (; sz > 0; sz--, bp++) {		for (tmo = 0; ; tmo++) {			ioctl(pp_user_fd, PPRSTATUS, &d);			if (d & LPTSTAT_WAIT)				break;			if (tmo > 1000)				return ret;		}		d = LPTCTRL_PROGRAM | LPTCTRL_DIRECTION | LPTCTRL_DATASTB;		ioctl(pp_user_fd, PPWCONTROL, &d);		for (tmo = 0; ; tmo++) {			ioctl(pp_user_fd, PPRSTATUS, &d);			if (!(d & LPTSTAT_WAIT))				break;			if (tmo > 1000)				return ret;		}		ioctl(pp_user_fd, PPRDATA, bp);		d = LPTCTRL_PROGRAM | LPTCTRL_DIRECTION;		ioctl(pp_user_fd, PPWCONTROL, &d);		ret++;	}	return ret;}unsigned parport_user_epp_write_addr(const void *buf, unsigned sz){	unsigned char *bp = (unsigned char *)buf;	unsigned ret = 0;	unsigned tmo;	unsigned char d;	d = LPTCTRL_PROGRAM | LPTCTRL_WRITE;	ioctl(pp_user_fd, PPWCONTROL, &d);	for (; sz > 0; sz--, bp++) {		ioctl(pp_user_fd, PPWDATA, bp);		for (tmo = 0; ; tmo++) {			ioctl(pp_user_fd, PPRSTATUS, &d);			if (d & LPTSTAT_WAIT)				break;			if (tmo > 1000)				return ret;		}		d = LPTCTRL_PROGRAM | LPTCTRL_WRITE | LPTCTRL_ADDRSTB;		ioctl(pp_user_fd, PPWCONTROL, &d);		for (tmo = 0; ; tmo++) {			ioctl(pp_user_fd, PPRSTATUS, &d);			if (!(d & LPTSTAT_WAIT))				break;			if (tmo > 1000)				return ret;		}		d = LPTCTRL_PROGRAM | LPTCTRL_WRITE;		ioctl(pp_user_fd, PPWCONTROL, &d);		ret++;	}	return ret;}unsigned parport_user_epp_read_addr(void *buf, unsigned sz){	unsigned char *bp = (unsigned char *)buf;	unsigned ret = 0;	unsigned tmo;	unsigned char d;	d = LPTCTRL_PROGRAM | LPTCTRL_DIRECTION;	ioctl(pp_user_fd, PPWCONTROL, &d);	for (; sz > 0; sz--, bp++) {		for (tmo = 0; ; tmo++) {			ioctl(pp_user_fd, PPRSTATUS, &d);			if (d & LPTSTAT_WAIT)				break;			if (tmo > 1000)				return ret;		}		d = LPTCTRL_PROGRAM | LPTCTRL_DIRECTION | LPTCTRL_ADDRSTB;		ioctl(pp_user_fd, PPWCONTROL, &d);		for (tmo = 0; ; tmo++) {			ioctl(pp_user_fd, PPRSTATUS, &d);			if (!(d & LPTSTAT_WAIT))				break;			if (tmo > 1000)				return ret;		}		ioctl(pp_user_fd, PPRDATA, bp);		d = LPTCTRL_PROGRAM | LPTCTRL_DIRECTION;		ioctl(pp_user_fd, PPWCONTROL, &d);		ret++;	}	return ret;}/* ---------------------------------------------------------------------- */static int ecp_forward(void){	unsigned tmo = 0x10000;	unsigned char d;	ioctl(pp_user_fd, PPRSTATUS, &d);	if (d & 0x20)		return 0;	/* Event 47: Set nInit high */	d = 0x26;	ioctl(pp_user_fd, PPWCONTROL, &d);	/* Event 49: PError goes high */	for (;;) {		ioctl(pp_user_fd, PPRSTATUS, &d);		if (d & 0x20)			break;		if (!(--tmo))			return -1;	}	/* start driving the bus */	d = 0x04;	ioctl(pp_user_fd, PPWCONTROL, &d);	return 0;}static int ecp_reverse(void){	unsigned tmo = 0x10000;	unsigned char d;	ioctl(pp_user_fd, PPRSTATUS, &d);	if (!(d & 0x20))		return 0;	d = 0x24;	ioctl(pp_user_fd, PPWCONTROL, &d);	/* Event 39: Set nInit low to initiate bus reversal */	d = 0x20;	ioctl(pp_user_fd, PPWCONTROL, &d);	for (;;) {		ioctl(pp_user_fd, PPRSTATUS, &d);		if (!(d & 0x20))			break;		if (!(--tmo))			return -1;	}	return 0;}unsigned parport_user_ecp_write_data(const void *buf, unsigned sz){	unsigned char *bp = (unsigned char *)buf;	unsigned ret;	unsigned char ctl, d;	unsigned tmo;	if (ecp_forward())		return 0;	ioctl(pp_user_fd, PPRCONTROL, &ctl);	ctl &= ~PARPORT_CONTROL_AUTOFD;	/* HostAck high (data, not command) */	ioctl(pp_user_fd, PPWCONTROL, &ctl);	for (ret = 0; ret < sz; ret++, bp++) {		ioctl(pp_user_fd, PPWDATA, bp);		d = ctl | PARPORT_CONTROL_STROBE;		ioctl(pp_user_fd, PPWCONTROL, &d);		tmo = 0;		do {			if (tmo > 0x1000)				return ret;			tmo++;			ioctl(pp_user_fd, PPRSTATUS, &d);		} while (d & PARPORT_STATUS_BUSY);		ioctl(pp_user_fd, PPWCONTROL, &ctl);		tmo = 0;		do {			if (tmo > 0x1000)				return ret;			tmo++;			ioctl(pp_user_fd, PPRSTATUS, &d);		} while (!(d & PARPORT_STATUS_BUSY));	}	return ret;}unsigned parport_user_ecp_write_addr(const void *buf, unsigned sz){	unsigned char *bp = (unsigned char *)buf;	unsigned ret;	unsigned char ctl, d;	unsigned tmo;	if (ecp_forward())		return 0;	ioctl(pp_user_fd, PPRCONTROL, &ctl);	ctl |= PARPORT_CONTROL_AUTOFD;	/* HostAck low (command, not data) */	ioctl(pp_user_fd, PPWCONTROL, &ctl);	for (ret = 0; ret < sz; ret++, bp++) {		ioctl(pp_user_fd, PPWDATA, bp);		d = ctl | PARPORT_CONTROL_STROBE;		ioctl(pp_user_fd, PPWCONTROL, &d);		tmo = 0;		do {			if (tmo > 0x1000)				return ret;			tmo++;			ioctl(pp_user_fd, PPRSTATUS, &d);		} while (d & PARPORT_STATUS_BUSY);		ioctl(pp_user_fd, PPWCONTROL, &ctl);		tmo = 0;		do {			if (tmo > 0x1000)				return ret;			tmo++;			ioctl(pp_user_fd, PPRSTATUS, &d);		} while (!(d & PARPORT_STATUS_BUSY));	}	return ret;}unsigned parport_user_ecp_read_data(void *buf, unsigned sz){	unsigned char *bp = (unsigned char *)buf;	unsigned ret = 0;	unsigned char ctl, stat;	int command;	unsigned tmo;	unsigned char d;	if (ecp_reverse())		return 0;	ioctl(pp_user_fd, PPRCONTROL, &ctl);	/* Set HostAck low to start accepting data. */	d = ctl | PARPORT_CONTROL_AUTOFD;	ioctl(pp_user_fd, PPWCONTROL, &d);	while (ret < sz) {		/* Event 43: Peripheral sets nAck low. It can take as                   long as it wants. */		tmo = 0;		do {			ioctl(pp_user_fd, PPRSTATUS, &stat);			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. */		ioctl(pp_user_fd, PPRDATA, bp);		/* Event 44: Set HostAck high, acknowledging handshake. */		d = ctl & ~PARPORT_CONTROL_AUTOFD;		ioctl(pp_user_fd, PPWCONTROL, &d);		/* Event 45: The peripheral has 35ms to set nAck high. */		tmo = 0;		do {			ioctl(pp_user_fd, PPRSTATUS, &stat);			if ((++tmo) > 0x10000)				goto out;		} while (!(stat & PARPORT_STATUS_ACK));		/* Event 46: Set HostAck low and accept the data. */		d = ctl | PARPORT_CONTROL_AUTOFD;		ioctl(pp_user_fd, PPWCONTROL, &d);		/* Normal data byte. */		bp++;		ret++;	} out:	return ret;}/* ---------------------------------------------------------------------- */unsigned parport_user_fpgaconfig_write(const void *buf, unsigned sz){	const unsigned char *bp = buf;	unsigned u;	for (u = 0; u < sz; u++, bp++)		parport_user_write_data(*bp);	return sz;}/* ---------------------------------------------------------------------- */const struct parport_ops parport_user_ops = {	parport_user_read_data,	parport_user_write_data,	parport_user_read_status,	parport_user_read_control,	parport_user_write_control,	parport_user_frob_control,	parport_user_epp_write_data,	parport_user_epp_read_data,	parport_user_epp_write_addr,	parport_user_epp_read_addr,	parport_user_ecp_write_data,	parport_user_ecp_read_data,	parport_user_ecp_write_addr,	parport_user_fpgaconfig_write};/* ---------------------------------------------------------------------- */

⌨️ 快捷键说明

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