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

📄 io.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
字号:
/* * Alpha IO and memory functions.. Just expand the inlines in the header * files.. */#include <linux/kernel.h>#include <linux/types.h>#include <linux/string.h>#include <asm/io.h>u8 _inb(unsigned long addr){	return __inb(addr);}u16 _inw(unsigned long addr){	return __inw(addr);}u32 _inl(unsigned long addr){	return __inl(addr);}void _outb(u8 b, unsigned long addr){	__outb(b, addr);}void _outw(u16 b, unsigned long addr){	__outw(b, addr);}void _outl(u32 b, unsigned long addr){	__outl(b, addr);}u8 ___raw_readb(unsigned long addr){	return __readb(addr);}u16 ___raw_readw(unsigned long addr){	return __readw(addr);}u32 ___raw_readl(unsigned long addr){	return __readl(addr);}u64 ___raw_readq(unsigned long addr){	return __readq(addr);}u8 _readb(unsigned long addr){	unsigned long r = __readb(addr);	mb();	return r;}u16 _readw(unsigned long addr){	unsigned long r = __readw(addr);	mb();	return r;}u32 _readl(unsigned long addr){	unsigned long r = __readl(addr);	mb();	return r;}u64 _readq(unsigned long addr){	unsigned long r = __readq(addr);	mb();	return r;}void ___raw_writeb(u8 b, unsigned long addr){	__writeb(b, addr);}void ___raw_writew(u16 b, unsigned long addr){	__writew(b, addr);}void ___raw_writel(u32 b, unsigned long addr){	__writel(b, addr);}void ___raw_writeq(u64 b, unsigned long addr){	__writeq(b, addr);}void _writeb(u8 b, unsigned long addr){	__writeb(b, addr);	mb();}void _writew(u16 b, unsigned long addr){	__writew(b, addr);	mb();}void _writel(u32 b, unsigned long addr){	__writel(b, addr);	mb();}void _writeq(u64 b, unsigned long addr){	__writeq(b, addr);	mb();}/* * Read COUNT 8-bit bytes from port PORT into memory starting at * SRC. */void insb (unsigned long port, void *dst, unsigned long count){	while (((unsigned long)dst) & 0x3) {		if (!count)			return;		count--;		*(unsigned char *) dst = inb(port);		((unsigned char *) dst)++;	}	while (count >= 4) {		unsigned int w;		count -= 4;		w = inb(port);		w |= inb(port) << 8;		w |= inb(port) << 16;		w |= inb(port) << 24;		*(unsigned int *) dst = w;		((unsigned int *) dst)++;	}	while (count) {		--count;		*(unsigned char *) dst = inb(port);		((unsigned char *) dst)++;	}}/* * Read COUNT 16-bit words from port PORT into memory starting at * SRC.  SRC must be at least short aligned.  This is used by the * IDE driver to read disk sectors.  Performance is important, but * the interfaces seems to be slow: just using the inlined version * of the inw() breaks things. */void insw (unsigned long port, void *dst, unsigned long count){	if (((unsigned long)dst) & 0x3) {		if (((unsigned long)dst) & 0x1) {			panic("insw: memory not short aligned");		}		if (!count)			return;		count--;		*(unsigned short* ) dst = inw(port);		((unsigned short *) dst)++;	}	while (count >= 2) {		unsigned int w;		count -= 2;		w = inw(port);		w |= inw(port) << 16;		*(unsigned int *) dst = w;		((unsigned int *) dst)++;	}	if (count) {		*(unsigned short*) dst = inw(port);	}}/* * Read COUNT 32-bit words from port PORT into memory starting at * SRC. Now works with any alignment in SRC. Performance is important, * but the interfaces seems to be slow: just using the inlined version * of the inl() breaks things. */void insl (unsigned long port, void *dst, unsigned long count){	unsigned int l = 0, l2;		if (!count)		return;		switch (((unsigned long) dst) & 0x3)	{	 case 0x00:			/* Buffer 32-bit aligned */		while (count--)		{			*(unsigned int *) dst = inl(port);			((unsigned int *) dst)++;		}		break;		/* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */		 case 0x02:			/* Buffer 16-bit aligned */		--count;				l = inl(port);		*(unsigned short *) dst = l;		((unsigned short *) dst)++;				while (count--)		{			l2 = inl(port);			*(unsigned int *) dst = l >> 16 | l2 << 16;			((unsigned int *) dst)++;			l = l2;		}		*(unsigned short *) dst = l >> 16;		break;	 case 0x01:			/* Buffer 8-bit aligned */		--count;				l = inl(port);		*(unsigned char *) dst = l;		((unsigned char *) dst)++;		*(unsigned short *) dst = l >> 8;		((unsigned short *) dst)++;		while (count--)		{			l2 = inl(port);			*(unsigned int *) dst = l >> 24 | l2 << 8;			((unsigned int *) dst)++;			l = l2;		}		*(unsigned char *) dst = l >> 24;		break;	 case 0x03:			/* Buffer 8-bit aligned */		--count;				l = inl(port);		*(unsigned char *) dst = l;		((unsigned char *) dst)++;		while (count--)		{			l2 = inl(port);			*(unsigned int *) dst = l << 24 | l2 >> 8;			((unsigned int *) dst)++;			l = l2;		}		*(unsigned short *) dst = l >> 8;		((unsigned short *) dst)++;		*(unsigned char *) dst = l >> 24;		break;	}}/* * Like insb but in the opposite direction. * Don't worry as much about doing aligned memory transfers: * doing byte reads the "slow" way isn't nearly as slow as * doing byte writes the slow way (no r-m-w cycle). */void outsb(unsigned long port, const void * src, unsigned long count){	while (count) {		count--;		outb(*(char *)src, port);		((char *) src)++;	}}/* * Like insw but in the opposite direction.  This is used by the IDE * driver to write disk sectors.  Performance is important, but the * interfaces seems to be slow: just using the inlined version of the * outw() breaks things. */void outsw (unsigned long port, const void *src, unsigned long count){	if (((unsigned long)src) & 0x3) {		if (((unsigned long)src) & 0x1) {			panic("outsw: memory not short aligned");		}		outw(*(unsigned short*)src, port);		((unsigned short *) src)++;		--count;	}	while (count >= 2) {		unsigned int w;		count -= 2;		w = *(unsigned int *) src;		((unsigned int *) src)++;		outw(w >>  0, port);		outw(w >> 16, port);	}	if (count) {		outw(*(unsigned short *) src, port);	}}/* * Like insl but in the opposite direction.  This is used by the IDE * driver to write disk sectors.  Works with any alignment in SRC. *  Performance is important, but the interfaces seems to be slow: * just using the inlined version of the outl() breaks things. */void outsl (unsigned long port, const void *src, unsigned long count){	unsigned int l = 0, l2;		if (!count)		return;		switch (((unsigned long) src) & 0x3)	{	 case 0x00:			/* Buffer 32-bit aligned */		while (count--)		{			outl(*(unsigned int *) src, port);			((unsigned int *) src)++;		}		break;		/* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */		 case 0x02:			/* Buffer 16-bit aligned */		--count;				l = *(unsigned short *) src << 16;		((unsigned short *) src)++;				while (count--)		{			l2 = *(unsigned int *) src;			((unsigned int *) src)++;			outl (l >> 16 | l2 << 16, port);			l = l2;		}		l2 = *(unsigned short *) src;		outl (l >> 16 | l2 << 16, port);		break;	 case 0x01:			/* Buffer 8-bit aligned */		--count;				l  = *(unsigned char *) src << 8;		((unsigned char *) src)++;		l |= *(unsigned short *) src << 16;		((unsigned short *) src)++;		while (count--)		{			l2 = *(unsigned int *) src;			((unsigned int *) src)++;			outl (l >> 8 | l2 << 24, port);			l = l2;		}		l2 = *(unsigned char *) src;		outl (l >> 8 | l2 << 24, port);		break;	 case 0x03:			/* Buffer 8-bit aligned */		--count;				l  = *(unsigned char *) src << 24;		((unsigned char *) src)++;		while (count--)		{			l2 = *(unsigned int *) src;			((unsigned int *) src)++;			outl (l >> 24 | l2 << 8, port);			l = l2;		}		l2  = *(unsigned short *) src;		((unsigned short *) src)++;		l2 |= *(unsigned char *) src << 16;		outl (l >> 24 | l2 << 8, port);		break;	}}/* * Copy data from IO memory space to "real" memory space. * This needs to be optimized. */void _memcpy_fromio(void * to, unsigned long from, long count){	/* Optimize co-aligned transfers.  Everything else gets handled	   a byte at a time. */	if (count >= 8 && ((long)to & 7) == (from & 7)) {		count -= 8;		do {			*(u64 *)to = __raw_readq(from);			count -= 8;			to += 8;			from += 8;		} while (count >= 0);		count += 8;	}	if (count >= 4 && ((long)to & 3) == (from & 3)) {		count -= 4;		do {			*(u32 *)to = __raw_readl(from);			count -= 4;			to += 4;			from += 4;		} while (count >= 0);		count += 4;	}			if (count >= 2 && ((long)to & 1) == (from & 1)) {		count -= 2;		do {			*(u16 *)to = __raw_readw(from);			count -= 2;			to += 2;			from += 2;		} while (count >= 0);		count += 2;	}	while (count > 0) {		*(u8 *) to = __raw_readb(from);		count--;		to++;		from++;	}}/* * Copy data from "real" memory space to IO memory space. * This needs to be optimized. */void _memcpy_toio(unsigned long to, const void * from, long count){	/* Optimize co-aligned transfers.  Everything else gets handled	   a byte at a time. */	/* FIXME -- align FROM.  */	if (count >= 8 && (to & 7) == ((long)from & 7)) {		count -= 8;		do {			__raw_writeq(*(const u64 *)from, to);			count -= 8;			to += 8;			from += 8;		} while (count >= 0);		count += 8;	}	if (count >= 4 && (to & 3) == ((long)from & 3)) {		count -= 4;		do {			__raw_writel(*(const u32 *)from, to);			count -= 4;			to += 4;			from += 4;		} while (count >= 0);		count += 4;	}			if (count >= 2 && (to & 1) == ((long)from & 1)) {		count -= 2;		do {			__raw_writew(*(const u16 *)from, to);			count -= 2;			to += 2;			from += 2;		} while (count >= 0);		count += 2;	}	while (count > 0) {		__raw_writeb(*(const u8 *) from, to);		count--;		to++;		from++;	}	mb();}/* * "memset" on IO memory space. */void _memset_c_io(unsigned long to, unsigned long c, long count){	/* Handle any initial odd byte */	if (count > 0 && (to & 1)) {		__raw_writeb(c, to);		to++;		count--;	}	/* Handle any initial odd halfword */	if (count >= 2 && (to & 2)) {		__raw_writew(c, to);		to += 2;		count -= 2;	}	/* Handle any initial odd word */	if (count >= 4 && (to & 4)) {		__raw_writel(c, to);		to += 4;		count -= 4;	}	/* Handle all full-sized quadwords: we're aligned	   (or have a small count) */	count -= 8;	if (count >= 0) {		do {			__raw_writeq(c, to);			to += 8;			count -= 8;		} while (count >= 0);	}	count += 8;	/* The tail is word-aligned if we still have count >= 4 */	if (count >= 4) {		__raw_writel(c, to);		to += 4;		count -= 4;	}	/* The tail is half-word aligned if we have count >= 2 */	if (count >= 2) {		__raw_writew(c, to);		to += 2;		count -= 2;	}	/* And finally, one last byte.. */	if (count) {		__raw_writeb(c, to);	}	mb();}voidscr_memcpyw(u16 *d, const u16 *s, unsigned int count){	if (! __is_ioaddr((unsigned long) s)) {		/* Source is memory.  */		if (! __is_ioaddr((unsigned long) d))			memcpy(d, s, count);		else			memcpy_toio(d, s, count);	} else {		/* Source is screen.  */		if (! __is_ioaddr((unsigned long) d))			memcpy_fromio(d, s, count);		else {			/* FIXME: Should handle unaligned ops and			   operation widening.  */			count /= 2;			while (count--) {				u16 tmp = __raw_readw((unsigned long)(s++));				__raw_writew(tmp, (unsigned long)(d++));			}		}	}}

⌨️ 快捷键说明

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