LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1092|回复: 3

linux驱动 ioremap 问题

[复制链接]
发表于 2007-10-9 15:33:36 | 显示全部楼层 |阅读模式
这是我在2.6下写的一个pc104的驱动, io映射, 只是实现读写功能, 但是pc104没有反映(用示波器直接测地址,数据引脚),pc104是16位的, 在x86上运行的, 不知道是ioremap()用错了,还是什么问题, 请高手指点:
#ifndef __KERNEL__
#define __KERNEL__
#endif

#ifndef MODULE
#define MODULE
#endif

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <linux/interrupt.h>
//#include <linux/cdev.h>
#include <linux/poll.h>
#include <linux/wait.h>
//#include <asm/arch/irqs.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
#include "pc1044.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("GOLDSEA");

#define pc104_major 126
#define pc104_minor 0
#define DEVICENAME "pc1044"
#define pc104_type unsigned int
#define pc104_base 0x0210 //物理地址
#define size 16
#define port_len unsigned int

unsigned short rbaseadd; //ioremap后的地址

static int pc104_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
static int pc104_open(struct inode *inode, struct file *filp);
static int pc104_release(struct inode *inode, struct file *filp);


static struct file_operations pc104_fops =
{
.owner = THIS_MODULE,
.ioctl = pc104_ioctl,
.open = pc104_open,
.release = pc104_release,
};

static int __init pc104_init(void)
{
int result;
result = register_chrdev(pc104_major, DEVICENAME, &pc104_fops);
if (result < 0)
{
printk(KERN_ERR DEVICENAME": Unable to get major %d\n", pc104_major);
// return result;
}
else
{
printk(KERN_ERR DEVICENAME": init OK !\n");
request_region(pc104_base, size, DEVICENAME);
rbaseadd = (unsigned int)ioremap(pc104_base, size);
// #define ReadPort0 inw *(rbaseadd + 0);
#define raddr0 (pc104_type *)(rbaseadd + 0)
#define raddr1 (pc104_type *)(rbaseadd + 0x02)
#define raddr2 (pc104_type *)(rbaseadd + 0x04)
#define raddr3 (pc104_type *)(rbaseadd + 0x06)
#define raddr4 (pc104_type *)(rbaseadd + 0x08)
#define raddr5 (pc104_type *)(rbaseadd + 0x0a)
#define raddr6 (pc104_type *)(rbaseadd + 0x0c)
#define raddr7 (pc104_type *)(rbaseadd + 0x0e)
#define raddr8 (pc104_type *)(rbaseadd + 0x10)
printk("base addr is %x\n, raddr0 is %x\n, raddr1 is %x\n",rbaseadd, (unsigned int)raddr0, (unsigned int)raddr1);
}

return result;
}

static void __exit pc104_exit(void)
{
int result;
result = unregister_chrdev(pc104_major, DEVICENAME);
if(result < 0)
{
printk(KERN_ERR DEVICENAME": unregister failure!\n");
}
else
{
printk(KERN_ERR DEVICENAME": unregister success !\n");
iounmap(raddr0);
release_region(pc104_base, size);
printk("ports are freed successfully!\n");
}

}

static int pc104_open(struct inode *inode, struct file *filp)
{
int num;
// unsigned int usage = 0;

num =MINOR (inode -> i_rdev);
if(num != pc104_minor)
{
return -ENODEV;
}
//MOD_INC_USE_COUNT;
//int try_module_get(&module);
// usage++;

return 0;
}

static int pc104_release(struct inode *inode, struct file *filp)
{
int num;
num = MINOR(inode -> i_rdev);

if(num != pc104_minor)
{
return -ENODEV;
}
// MOD_DEC_USE_COUNT;
// usage--;
return 0;
}


static int pc104_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{

int num;
u16 temp;

num = MINOR(inode ->i_rdev);
if(num != pc104_minor)
{
return -ENOTTY;
}
if(_IOC_TYPE(cmd) != PC104_IOC_MAGIC)
{
return -ENOTTY;
}
if(_IOC_NR(cmd) >= PC104_MAX)
{
return -ENOTTY;
}

switch(cmd)
{
case READ0:
temp = inw((port_len)*raddr0);
put_user(temp, (unsigned long *)arg);
break;

case READ1:
temp = inw((port_len)*raddr1);
put_user(temp, (unsigned long *)arg);
break;

case READ2:
temp = inw((port_len)*raddr2);
put_user(temp, (unsigned long *)arg);
break;

case READ3:
temp = inw((port_len)*raddr3);
put_user(temp, (unsigned long *)arg);
break;

case READ4:
temp = inw((port_len)*raddr4);
put_user(temp, (unsigned long *)arg);
break;
case WRITE5:
get_user(temp, (unsigned long *)arg);
outw(temp, (port_len)*raddr0);
break;
case WRITE6:
get_user(temp, (unsigned long *)arg);
outw(temp, (port_len)*raddr1);
break;
case WRITE7:
get_user(temp, (unsigned long*)arg);
outw(temp, (port_len)*raddr2);
break;
case WRITE8:
get_user(temp, (unsigned long *)arg);
outw(temp, (port_len)*raddr3);
break;
default:
return -ENOTTY;
}
return 0;
}

module_init(pc104_init);
module_exit(pc104_exit);
 楼主| 发表于 2007-10-9 15:54:53 | 显示全部楼层
对了, 打印的rbaseaddr = 1279d210, 为什么没有在0xc0000000以上呢?是不是ioremap有问题啊
回复 支持 反对

使用道具 举报

发表于 2007-10-10 10:34:43 | 显示全部楼层
建议你这个最好转到内核版
回复 支持 反对

使用道具 举报

发表于 2007-10-11 09:13:19 | 显示全部楼层
ioremap函数用的不对,你查一下,另外被映射后的IO内存要用ioread/iowrite系统函数访问,还有楼主你代码不太严谨啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表