📄 readio_end_lk.c
字号:
/******************************************************************************************
Function: Linux Driver module for accessing IO port in Intel IPX425
include led port,red port,watchdog/count port, addr port,
key port.
author:liuxs -- Hollysys .
Date:2005-10-25
Kernel Dep: linux 2.6.20
bugfix: 1. when read addr base,if only read once,the return value is wrong ,the second read
will get the right value. 2006/07/27
2.when read/write 16 bit port,readw/writew cannot work well,should directly use
addr :2006-12-12
******************************************************************************************/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#define READIO 1
#define WRITEIO 2
#define WATCHDOG_REG 1
#define LED_REG 2
#define RED_REG 3
#define ADDR_REG 4
#define AHB_IOSTATE_REG 5
#define KEY_REG 6
#define DOUBLE_REG 7
#define FREE_COUNT_REG 8
#define AHB_CST_REG 9
#define BAT_STATUS_REG 10
#define COM_REG 11 //wangyue added
#define SOE_COUNT_REG 12 //Added by ZhuPenghui
#define INVALID_REG -1
//watchdog/FREE COUNT base
#define WATCHDOG_BASE 0x54FFFFE0 //clr
#define WATCHDOG_SET 0x54FFFFE2 //WATCHDOG time setting
#define WATCHDOG_CLR 0x54FFFFE1 //
#define WATCHDOG_LEN 4
#define BAT_STATUS_ADDR 0x56FFFFE0
#define BAT_STATUS_LEN 4
#define LED_BASE 0x54FFFFF0
#define LED_LEN 8
#define KEY_BASE 0x54FFFFC0 //key base
#define ADDR_BASE 0x54FFFFC1 //addr base
#define KEY_LEN 2
#define DOUBLE_BASE 0x54FFFFBF
#define DOUBLE_LEN 1
//AHB iostate
#define AHB_IOSTATE_BASE 0x52FFF000 //2-9 io module
//#define AHB_IOSTATE_BASE 0x52FFF001 //10-15 io module
#define AHB_IOSTATE_ACTIVE 0x52FFF002 //work or listening
#define AHB_IOSTATE_LEN 4
//free count
#define FREE_COUNT_BASE 0x55FFBFF0
#define FREE_COUNT_LEN 16
//SOE counter
#define SOE_COUNT_BASE 0x55FFBFE0 //Added by ZhuPenghui
#define SOE_COUNT_LEN 16
//Ahb cst time
#define AHB_CSTTIME_ADDR 0x52fff010
#define AHB_CSTTIME_LEN 16
//com
#define COM_BASE_ADDR 0x54ffffdf //wangyue added
#define COM_BASE_LEN 1
volatile unsigned char * watchdogbase;
volatile unsigned char * ledbase;
volatile unsigned char * ahbiostatebase;
volatile unsigned char * keybase;
volatile unsigned char * doublebase;
volatile unsigned short * freecountbase;
volatile unsigned short * soecountbase; //Added by ZhuPenghui
volatile unsigned char * ahbcstimebase;
volatile unsigned char * batstatusbase;
volatile unsigned char * combase; //wangyue added
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/fs.h> /* everything... */
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/ioport.h>
int ioport_major=0;
MODULE_LICENSE("DUAL BSD/GPL");
unsigned char safe_readb(unsigned long addr);
void delaytime(int data);
int ioport_open (struct inode *inode, struct file *filp);
int ioport_release(struct inode *ino, struct file *f);
int ioport_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long *arg);
struct file_operations ioport_fops = {
open: ioport_open,
ioctl: ioport_ioctl,
release: ioport_release,
};
//chech valid of parameter
int check_arg_valid(unsigned long addr)
{
// printk(KERN_INFO"para in readio addr=%08X\n",addr);
if((addr>=WATCHDOG_BASE) && (addr <=WATCHDOG_BASE+WATCHDOG_LEN))
return WATCHDOG_REG;
if((addr>=LED_BASE) && (addr<=LED_BASE+LED_LEN))
return LED_REG;
if((addr>=AHB_IOSTATE_BASE) && (addr<=AHB_IOSTATE_BASE+AHB_IOSTATE_LEN))
return AHB_IOSTATE_REG;
if((addr>=KEY_BASE) && (addr<=KEY_BASE+KEY_LEN))
return KEY_REG;
if((addr>=DOUBLE_BASE) && (addr<=DOUBLE_BASE+DOUBLE_LEN))
return DOUBLE_REG;
if((addr>=FREE_COUNT_BASE) && (addr<=FREE_COUNT_BASE+FREE_COUNT_LEN))
return FREE_COUNT_REG;
if((addr>=SOE_COUNT_BASE) && (addr<=SOE_COUNT_BASE+SOE_COUNT_LEN))
return SOE_COUNT_REG;
if((addr>=AHB_CSTTIME_ADDR) && (addr<=AHB_CSTTIME_ADDR+AHB_CSTTIME_LEN))
return AHB_CST_REG;
if((addr>=BAT_STATUS_ADDR) && (addr<=BAT_STATUS_ADDR+BAT_STATUS_LEN))
return BAT_STATUS_REG;
if( addr==COM_BASE_ADDR ) //wangyue added
return COM_REG;
printk(KERN_INFO"para is invalid in readio addr=%08X\n",addr);
return INVALID_REG;
}
int ioport_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long *arg)
{
int res=0;
unsigned long port;
unsigned long write_value;
unsigned char *ucioaddr; //byte
unsigned short *usioaddr; //16 bit
int check_res=-1;
if(arg==NULL)
return -1;
// printk(KERN_INFO"in ioctl\n");
port=arg[0];
write_value=arg[1];
check_res=check_arg_valid(port);
switch(check_res){
case WATCHDOG_REG:
ucioaddr=watchdogbase+port-WATCHDOG_BASE;
break;
case LED_REG:
ucioaddr=ledbase+port-LED_BASE;
break;
case AHB_IOSTATE_REG:
ucioaddr=ahbiostatebase+port-AHB_IOSTATE_BASE;
break;
case KEY_REG:
ucioaddr=keybase+port-KEY_BASE;
break;
case DOUBLE_REG:
ucioaddr=doublebase+port-DOUBLE_BASE;
break;
case FREE_COUNT_REG:
if((port%2)!=0)
return -1;
else
usioaddr=(unsigned short *)freecountbase+(port-FREE_COUNT_BASE)/2;
break;
case SOE_COUNT_REG: //Added by ZhuPenghui
if((port%2)!=0)
return -1;
else
usioaddr=(unsigned short *)soecountbase+(port-SOE_COUNT_BASE)/2;
break;
case AHB_CST_REG:
ucioaddr=ahbcstimebase+port-AHB_CSTTIME_ADDR;
break;
case BAT_STATUS_REG:
ucioaddr=batstatusbase+port-BAT_STATUS_ADDR;
break;
case COM_REG:
ucioaddr=combase+port-COM_BASE_ADDR; //wangyue added
break;
case INVALID_REG:
return -1;
default:
return -1;
}
switch(cmd) {
case READIO:
if(check_res==FREE_COUNT_REG)
{
//res=readw(usioaddr);
res=*(volatile unsigned short *)usioaddr;
break;
}
else
{
if(check_res==SOE_COUNT_REG)
{
res=*(volatile unsigned short *)usioaddr;
break;
}
else
{
res=readb(ucioaddr);
}
}
break;
case WRITEIO:
if(check_res==FREE_COUNT_REG)
{
// writew(write_value,usioaddr);
*(volatile unsigned short *)usioaddr=write_value;
}
else
{
if(check_res==SOE_COUNT_REG)
{
*(volatile unsigned short *)usioaddr=write_value;
break;
}
else
{
writeb(write_value,ucioaddr);
}
}
break;
default:
res=-1;
break;
}
return res;
}
int ioport_open(struct inode *inode, struct file *filp)
{
printk("<0>,in open \n");
// MOD_INC_USE_COUNT;
return 0;
}
int ioport_release(struct inode *inode, struct file *filp)
{
// MOD_DEC_USE_COUNT;
return 0;
}
int init_module(void)
{
int result=0;
printk(KERN_INFO"hello release vern 12-06\n");
watchdogbase=(volatile unsigned char *)ioremap_nocache(WATCHDOG_BASE,WATCHDOG_LEN);
ledbase=(volatile unsigned char *)ioremap_nocache(LED_BASE,LED_LEN);
ahbiostatebase=(volatile unsigned char *)ioremap_nocache(AHB_IOSTATE_BASE,AHB_IOSTATE_LEN);
keybase=(volatile unsigned char *)ioremap_nocache(KEY_BASE,KEY_LEN);
doublebase=(volatile unsigned char *)ioremap_nocache(DOUBLE_BASE,DOUBLE_LEN);
freecountbase=(volatile unsigned short *)ioremap_nocache(FREE_COUNT_BASE,FREE_COUNT_LEN);
soecountbase=(volatile unsigned short *)ioremap_nocache(SOE_COUNT_BASE,SOE_COUNT_LEN); //Added by ZhuPenghui
ahbcstimebase=(volatile unsigned char *)ioremap_nocache(AHB_CSTTIME_ADDR,AHB_CSTTIME_LEN);
batstatusbase=(volatile unsigned char *)ioremap_nocache(BAT_STATUS_ADDR,BAT_STATUS_LEN);
combase=(volatile unsigned char *)ioremap_nocache(COM_BASE_ADDR,COM_BASE_LEN); //wangyue added
result = register_chrdev(232, "readio", &ioport_fops);
ioport_major=result;
// writeb(0x01,redbase); //first set state as slave;
printk(KERN_INFO"major133333 =%d \n",result);
return 0;
}
void cleanup_module(void)
{
int result=0;
if(watchdogbase!=NULL)
iounmap(watchdogbase);
if(ledbase!=NULL)
iounmap(ledbase);
if(keybase!=NULL)
iounmap(keybase);
if(doublebase!=NULL)
iounmap(doublebase);
if(freecountbase!=NULL)
iounmap(freecountbase);
if(soecountbase!=NULL) //Added by ZhuPenghui
iounmap(soecountbase);
if(ahbiostatebase)
iounmap(ahbiostatebase);
if(combase!=NULL)
iounmap(combase); //wangyue added
result= unregister_chrdev(ioport_major, "readio");
printk(KERN_INFO"goodbye\n");
}
void delaytime(int data)
{
int i;
int j=data;
int k;
for(i=0;i<10;i++)
for(j=0;j<data;j++)
{
k=i+j;
}
}
unsigned char safe_readb(unsigned long addr)
{
unsigned char i=0;
unsigned char j=0;
unsigned char tmp=0;
unsigned char tmp2=0;
tmp2=readb(addr);
while(i<5)
{
tmp=readb(addr);
delaytime(2);
if(tmp!=tmp2)
{
i=0;
}
tmp2=tmp;
i++;
j++;
if(j>=15)
break;
}
return tmp2;
}
//module_init(ioport_init_module);
//module_exit(ioport_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -