📄 do_8255.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 + -