|
这是我在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); |
|