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

📄 do_8255.c

📁 基于linux2.4内核下,外接于AT91RM9200总线上的8255驱动及测试程序。硬件平台为:中嵌科技的CE9200-1开发板
💻 C
字号:
/*****************************************************************************
;Institue of Automation, Chinese Academy of Sciences
;www.hyesco.com
;Description: 	8255 driver on Linux for DO
;Date:					2007-02-05		
;Author:						
;E_mail:			
*****************************************************************************/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h> 				
#include <asm/arch/AT91RM9200_SYS.h>

#include <asm/arch/hardware.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/devfs_fs_kernel.h>

//*********************************************************
//数据类型定义:
//*********************************************************
#define	U32	volatile unsigned int			
#define	U16	volatile unsigned short		
#define	U8	volatile unsigned char

//*********************************************************
//82C55端口地址结构定义:	 
//*********************************************************
#define PA1_8255_ADDR	0x00
#define PB1_8255_ADDR	0x02
#define PC1_8255_ADDR	0x04
#define CW1_8255_ADDR	0x06

//*********************************************************
//系统外设基地址:
//0x5000,0000: NCS4;
//*********************************************************
#define	PHYADDR   		0x50000000L
#define ADDR_Size			0x20				

//*********************************************************
//全局变量、常量定义:
//*********************************************************
static int major=0;						
static char dev_name[]="DO_8255";
static char number[]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09};          //0----9
static volatile unsigned char * IO_Addr = NULL;
static unsigned int CHA;							//用于存放通道号;

//*********************************************************
//函数定义;
//*********************************************************
static int s_open(struct inode * s_node,struct file * s_file);
static int s_write(struct file*s_file, const char*w_buf,int len,loff_t* loff);
static int s_ioctl(struct inode *s_node, struct file *file, unsigned int cmd, unsigned long arg);

//*********************************************************
//文件操作结构体;
//*********************************************************
struct file_operations Tmint_fops_ADDR=
{
		write	:	(void(*)) s_write,
		open	:	(void(*)) s_open,
		ioctl :	(void(*)) s_ioctl,
		
 };

//*********************************************************
//延时函数;
//*********************************************************
void Delay(unsigned int x)
{
		unsigned int i,j;
		for(i=0;i<=x;i++)
			for(j=0;j<100;j++)
				;
}

//*********************************************************
//初始化模块函数;
//*********************************************************
static devfs_handle_t devfs_handle;
static int __init s_init_module(void)
{
    int ret;

		//注册模块;
		if ((ret=devfs_register_chrdev(major,dev_name,&Tmint_fops_ADDR)) < 0)
			  {
			   printk("\r\n<1>Register Fail!\r\n");        
			   return ret;
			  }

		//动态分配主设备号;
		if(major == 0)
			   major = ret;
		
		//建立设备文件;
		devfs_handle = devfs_register(NULL, dev_name ,DEVFS_FL_DEFAULT,
			major, 0, S_IFCHR | S_IRUSR | S_IWUSR,&Tmint_fops_ADDR, NULL);
		
		//申请内存区域,以检测该地址空间是否被使用;
		if (!request_mem_region(PHYADDR,ADDR_Size,dev_name))
	    printk("Error request mem address! \r\n");         
    		
		//进行内存区域的映射,把物理地址映射为逻辑地址;  
		IO_Addr = (unsigned char*)ioremap_nocache(PHYADDR,ADDR_Size);
		
		return 0;
}

//*********************************************************
//清除模块函数;
//*********************************************************
static void __exit s_cleanup_module(void)
{
    int retv;
 		
 		//取消内存区域映射;
		iounmap((unsigned char *)IO_Addr);
	
		//释放申请的内存区域;
		release_mem_region(PHYADDR,ADDR_Size);
		
		//注销模块;
		retv=devfs_unregister_chrdev(major,dev_name);
		if(retv<0)
			{
    		printk("<1>IO_ADDR UnRegister Fail!\n");
   			return ;
			}
		printk("<1>IO_ADDR:Good Bye!\n");
}

//*********************************************************
//open函数;
//*********************************************************
static int s_open(struct inode * s_node,struct file * s_file)
{
		//定义EBI控制寄存器的读写参数,参考AT91RM9200用户手册P190;
		/* AT91_SYS->EBI_SMC2_CSR[7]= AT91C_SMC2_NWS| AT91C_SMC2_WSEN
			| AT91C_SMC2_TDF | AT91C_SMC2_BAT | AT91C_SMC2_DBW_16
			| AT91C_SMC2_RWHOLD|AT91C_SMC2_ACSS_3_CYCLES;
		*/
		AT91_SYS->EBI_SMC2_CSR[4]= 0x11003183;
		
		//PA1、PB1、PC1均设置为通用输出模式;
		writeb(0x80,(volatile unsigned char *)(IO_Addr + CW1_8255_ADDR));
				
		return 0;
}

//*********************************************************
//ioctl函数 
//*********************************************************
static int s_ioctl(struct inode *s_node, struct file *file, unsigned int cmd, unsigned long arg)
{
	switch(arg)
		{
		case 0:
			CHA = 0;		//选择通道PA1; 
			break;
		case 1:
			CHA = 1;		//选择通道PB1; 
			break;
		case 2:
			CHA = 2;		//选择通道PC1; 
			break;
			
		default:
      break;
			
		}
	return 0;
}

//*********************************************************
//write函数;
//********************************************************* 
static int s_write(struct file*s_file, const char *w_buf,int len,loff_t* loff)
{
		unsigned char	IO_data;
			
		//从用户空间拷贝数据到内核空间;		
		if(copy_from_user(&IO_data,w_buf,sizeof(unsigned char)))	
			return -EFAULT;
	
		//根据不同的通道号,送出相应的数据;
		switch(CHA)
			{
			case 0:
				writeb(IO_data,(volatile unsigned char *)(IO_Addr + PA1_8255_ADDR));
				break;
			case 1:
				writeb(IO_data,(volatile unsigned char *)(IO_Addr + PB1_8255_ADDR));
				break;
			case 2:
				writeb(IO_data,(volatile unsigned char *)(IO_Addr + PC1_8255_ADDR));
				break;
			default:
				break;
				
			}
   	return 0;      		
}

module_init(s_init_module);
module_exit(s_cleanup_module);
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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