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

📄 pio_ppc860.c

📁 umon bootloader source code, support mips cpu.
💻 C
字号:
/* pio.c:
 *	Support the basic ability to configure and set/clear parallel IO pins.
 *
 *	General notice:
 *	This code is part of a boot-monitor package developed as a generic base
 *	platform for embedded system designs.  As such, it is likely to be
 *	distributed to various projects beyond the control of the original
 *	author.  Please notify the author of any enhancements made or bugs found
 *	so that all may benefit from the changes.  In addition, notification back
 *	to the author will allow the new user to pick up changes that may have
 *	been made by other users after this version of the code was distributed.
 *
 *	Note1: the majority of this code was edited with 4-space tabs.
 *	Note2: as more and more contributions are accepted, the term "author"
 *		   is becoming a mis-representation of credit.
 *
 *	Original author:	Ed Sutter
 *	Email:				esutter@lucent.com
 *	Phone:				908-582-2351
 */
#include "config.h"
#include "cpuio.h"
#include "ctype.h"
#include "genlib.h"
#include "mpc860.h"
#include "arch_ppc.h"

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;


#define PIO_IN	1
#define PIO_OUT	2
#define PIO_GP	3
#define PIO_DED	4
#define ALL_PIO	0x7f

void	pioshow(char);

/* Pio():
	Display/Configure/Modify MPC860 PIO pins.
	Syntax
	pio [options] {A|B|C|D} {bit #} [0|1]

	  For port A, bit # range = 0-15
	  For port B, bit # range = 14-31
	  For port C, bit # range = 4-15
	  For port D, bit # range = 3-15
	  Options:
		-i 	configure as in
		-o 	configure as out
		-g 	configure as gpio
		-d 	configure as dedicated

    Note: recall that the PowerPC documentation reverses the order of bits
	(for some ridiculous reason), so bit 1 in a 32 bit register corresponds
	to 0x80000000, not 0x00000001; likewise, bit 1 in a 16 bit register is
	0x8000, not 0x0001.
*/

extern EPPC	*IMMRBase;

#if INCLUDE_PIO

char *PioHelp[] = {
	"Programmable IO Interface",
	"-[iogdw] {PortName} [bit #] [0|1]",
	" -i   input",
	" -o   output",
	" -g   gpio",
	" -d   dedicated",
	" -w   waitonbit",
	0,
};

int
Pio(argc,argv)
int argc;
char *argv[];
{
	char	portName;
	int	opt, bitnum, val, config, waitonbit, boor;
	volatile ushort	*dat16, *dir16, *par16;
	volatile ulong	*dat32, *dir32, *par32;

	dat16 = dir16 = par16 = (ushort *)0;
	dat32 = dir32 = par32 = (ulong *)0;

	/* Set IMMRBase pointing to the MPC860's internal register memory map */
	/* (should have already been done by InitUART(), but just do it again */
	/* to be safe). */
   	IMMRBase = (EPPC *)(ppcMfimmr() & 0xFFFF0000);

	/* Show all ports: */
	if (argc == 1) {
		pioshow(ALL_PIO);
		return(0);
	}

	/* Show one port: */
	if (argc == 2) {
		portName = (char)toupper(argv[optind][0]);
		switch(portName) {
		case 'A':
		case 'B':
		case 'C':
		case 'D':
			pioshow(portName);
			return(0);
		default:
			return(-1);
		}
	}

	config = 0;
	waitonbit = 0;
	boor = 0;
	while((opt=getopt(argc,argv,"iogdw")) != -1) {
		switch(opt) {
		case 'o':
			config = PIO_OUT;
			break;
		case 'g':
			config = PIO_GP;
			break;
		case 'd':
			config = PIO_DED;
			break;
		case 'i':
			config = PIO_IN;
			break;
		case 'w':
			waitonbit = 1;
			break;
		default:
			return(0);
		}
	}

	if (argc < (optind+2))
		return(-1);

	portName = (char)toupper(argv[optind][0]);
	bitnum = (int)strtol(argv[optind+1],(char **)0,0);

	/* Clear bit-out-of-range flag, then check for bit out of range... */
	switch(portName) {
		case 'A':
			if ((bitnum < 0) || (bitnum > 15)) 
				boor = 1;
			else {
				dat16 = &IMMRBase->pio_padat;			/* data */
				dir16 = &IMMRBase->pio_padir;			/* direction */
				par16 = &IMMRBase->pio_papar;			/* pin assignment */
			}
			break;
		case 'B':
			if ((bitnum < 14) || (bitnum > 31)) 
				boor = 1;
			else {
				dat32 = &IMMRBase->pip_pbdat;
				dir32 = &IMMRBase->pip_pbdir;
				par32 = &IMMRBase->pip_pbpar;
			}
			break;
		case 'C':
			if ((bitnum < 4) || (bitnum > 15)) 
				boor = 1;
			else {
				dat16 = &IMMRBase->pio_pcdat;
				dir16 = &IMMRBase->pio_pcdir;
				par16 = &IMMRBase->pio_pcpar;
			}
			break;
		case 'D':
			if ((bitnum < 3) || (bitnum > 15)) 
				boor = 1;
			else {
				dat16 = &IMMRBase->pio_pddat;
				dir16 = &IMMRBase->pio_pddir;
				par16 = &IMMRBase->pio_pdpar;
			}
			break;
		default:
			printf("Invalid port: %c\n",portName);
			return(0);
	}

	if (boor) {
		printf("Bit %d out of range for port %c\n",bitnum,portName);
		return(0);
	}

	if (waitonbit) {
		if (argc != (optind+3)) {
			printf("-w requires port, bit and value\n");
			return(-1);
		}
		val = argv[optind+2][0] & 1;
		if (portName == 'B') {
			while(1) {
				if ((val == 1) && (*dat32 & (ulong)(0x80000000>>bitnum)))
					break;
				else if ((val == 0) && !(*dat32 & (ulong)(0x80000000>>bitnum)))
					break;
			}
		}
		else {
			while(1) {
				if ((val == 1) && (*dat16 & (ushort)(0x8000 >> bitnum)))
					break;
				else if ((val == 0) && !(*dat16 & (ushort)(0x8000 >> bitnum)))
					break;
			}
		}
		return(0);
	}
	/* If config, then set up direction or control */
	if (config) {
		if (argc != (optind+2))
			return(-1);
		if (portName == 'B') {
			switch(config) {
			case PIO_OUT:
				*dir32 |= (ulong)(0x80000000 >> bitnum);
				break;
			case PIO_IN:
				*dir32 &= (ulong)~(0x80000000 >> bitnum);
				break;
			case PIO_GP:
				*par32 &= (ulong)~(0x80000000 >> bitnum);
				break;
			case PIO_DED:
				*par32 |= (ulong)(0x80000000 >> bitnum);
				break;
			}
		}
		else {
			switch(config) {
			case PIO_OUT:
				*dir16 |= (ushort)(0x8000 >> bitnum);
				break;
			case PIO_IN:
				*dir16 &= (ushort)~(0x8000 >> bitnum);
				break;
			case PIO_GP:
				*par16 &= (ushort)~(0x8000 >> bitnum);
				break;
			case PIO_DED:
				*par16 |= (ushort)(0x8000 >> bitnum);
				break;
			}
		}
		return(0);
	}

	/* If config is not set, then it must be a read or write request... */
	/* If third arg is present, then write; else read. */
	if (argc == optind+3) {
		val = argv[optind+2][0] & 1;
		if (portName == 'B') {
			if (val)
				*dat32 |= (ulong)(0x80000000 >> bitnum);
			else
				*dat32 &= (ulong)~(0x80000000 >> bitnum);
		}
		else {
			if (val)
				*dat16 |= (ushort)(0x8000 >> bitnum);
			else
				*dat16 &= (ushort)~(0x8000 >> bitnum);
		}
	}
	else {			/* Read a pio bit */
		if (portName == 'B') {
			printf("P%c%d = %d\n",portName,bitnum,
			    (*dat32 & (ulong)(0x80000000 >> bitnum)) ? 1:0);
		}
		else {
			printf("P%c%d = %d\n",portName,bitnum,
			    (*dat16 & (ushort)(0x8000000 >> bitnum)) ? 1:0);
		}
	}
	return(0);
}

void
pioshow(char port)
{
	int i;
	ulong	mask;

	if (port == 'A' || port == ALL_PIO) {
		printf("PORTA bits 0-15...\n");
		printf("PAPAR: 0x%04x, PADIR: 0x%04x, PADAT: 0x%04x\n",
		    IMMRBase->pio_papar, IMMRBase->pio_padir, IMMRBase->pio_padat);
		for (mask=0x8000,i=0;i<16;i++,mask >>= 1) {
			printf("  PA%02d: %s %s %d\n",i,
			    (IMMRBase->pio_papar & mask) ? "dedicated" : "gpio",
			    (IMMRBase->pio_padir & mask) ? "output" : "input",
			    (IMMRBase->pio_padat & mask) ? 1 : 0);
		}
	}

	if (port == 'B' || port == ALL_PIO) {
		printf("\nPORTB bits 14-31...\n");
		printf("PBPAR: 0x%08x, PBDIR: 0x%08x, PBDAT: 0x%08x\n",
		    IMMRBase->pip_pbpar, IMMRBase->pip_pbdir, IMMRBase->pip_pbdat);
		for (mask=0x80000000>>14,i=14;i<32;i++,mask >>= 1) {
			printf("  PB%02d: %s %s %d\n",i,
			    (IMMRBase->pip_pbpar & mask) ? "dedicated" : "gpio",
			    (IMMRBase->pip_pbdir & mask) ? "output" : "input",
			    (IMMRBase->pip_pbdat & mask) ? 1 : 0);
		}
	}

	if (port == 'C' || port == ALL_PIO) {
		printf("PORTC bits 4-15...\n");
		printf("PCPAR: 0x%04x, PCDIR: 0x%04x, PCDAT: 0x%04x\n",
		    IMMRBase->pio_pcpar, IMMRBase->pio_pcdir, IMMRBase->pio_pcdat);
		for (mask=0x8000>>4,i=4;i<16;i++,mask >>= 1) {
			printf("  PC%02d: %s %s %d\n",i,
			    (IMMRBase->pio_pcpar & mask) ? "dedicated" : "gpio",
			    (IMMRBase->pio_pcdir & mask) ? "output" : "input",
			    (IMMRBase->pio_pcdat & mask) ? 1 : 0);
		}
	}

	if (port == 'D' || port == ALL_PIO) {
		printf("PORTD bits 3-15...\n");
		printf("PDPAR: 0x%04x, PDDIR: 0x%04x, PDDAT: 0x%04x\n",
		    IMMRBase->pio_pdpar, IMMRBase->pio_pddir, IMMRBase->pio_pddat);
		for (mask=0x8000>>3,i=3;i<16;i++,mask >>= 1) {
			printf("  PD%02d: %s %s %d\n",i,
			    (IMMRBase->pio_pdpar & mask) ? "dedicated" : "gpio",
			    (IMMRBase->pio_pddir & mask) ? "output" : "input",
			    (IMMRBase->pio_pddat & mask) ? 1 : 0);
		}
	}
}
#endif

int
pioget(char port,int bitnum)
{
	ulong	mask;

	mask = 0x8000 >> bitnum;
	switch(tolower(port)) {
		case 'a':
			return((IMMRBase->pio_padat & (ushort)mask) ? 1:0);
		case 'b':
			mask = 0x80000000 >> bitnum;
			return((IMMRBase->pip_pbdat & (ulong)mask) ? 1:0);
		case 'c':
			return((IMMRBase->pio_pcdat & (ushort)mask) ? 1:0);
		case 'd':
			return((IMMRBase->pio_pddat & (ushort)mask) ? 1:0);
	}
	return(-1);
}

void
pioclr(char port,int bitnum)
{
	ulong	mask;

	mask = 0x8000 >> bitnum;
	switch(tolower(port)) {
		case 'a':
			IMMRBase->pio_padat &= (ushort)~mask;
			break;
		case 'b':
			mask = 0x80000000 >> bitnum;
			IMMRBase->pip_pbdat &= (ulong)~mask;
			break;
		case 'c':
			IMMRBase->pio_pcdat &= (ushort)~mask;
			break;
		case 'd':
			IMMRBase->pio_pddat &= (ushort)~mask;
			break;
	}
}

void
pioset(char port,int bitnum)
{
	ulong	mask;

	mask = 0x8000 >> bitnum;
	switch(tolower(port)) {
		case 'a':
			IMMRBase->pio_padat |= (ushort)mask;
			break;
		case 'b':
			mask = 0x80000000 >> bitnum;
			IMMRBase->pip_pbdat |= (ulong)mask;
			break;
		case 'c':
			IMMRBase->pio_pcdat |= (ushort)mask;
			break;
		case 'd':
			IMMRBase->pio_pddat |= (ushort)mask;
			break;
	}
}

⌨️ 快捷键说明

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