hpi 驱动源码
2019-07-13 18:58发布
生成海报
Author-------Dansen-----xzd2734@163.com
给出我写的源码,其中中断和几个变量是为了追球的任务特别添加的,基本不是通用的,还能继续改进的吧,不过暂时先这么用了。没有对中断中使用的共享变量进行保护啊,这是错误的地方,至少要关中断啊!再修改了!
/*
Dsp hpi interface with ARM 9 for s3c2410
Author--------Dansen----2007.09.05
*/
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif
#include
#include
#include /* printk() */
#include /* kmalloc() */
#include
#include /* everything... */
#include /* error codes */
#include /* size_t */
#include
#include /* O_ACCMODE */
#include
#include
#include
#include
//#define HPI_DEBUG
#undef PDEBUG /* undef it, just in case */
#ifdef HPI_DEBUG
# ifdef __KERNEL__ /* This one if debugging is on, and kernel space */
# define PDEBUG(fmt, args...) printk( KERN_EMERG "hpi: " fmt, ## args)
# else /* This one for user space */
# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
# endif
#else
# define PDEBUG(fmt, args...) /* not debugging: nothing */
#endif
#define HPI_BASEADDR 0x10000300 // BANK 2
#define HPI_MAJOR 200 /* dynamic major by default */
#define HPI_INT IRQ_EINT19
#define HPI_MAGIC 'K'
#define HPI_RESET _IO(HPI_MAGIC, 0)
#define Write_HPIC _IO(HPI_MAGIC, 1)
#define Read_HPIC _IO(HPI_MAGIC, 2)
#define Write_HPIA _IO(HPI_MAGIC, 3)
#define Read_HPIA _IO(HPI_MAGIC, 4)
#define Write_HPID_Auto _IO(HPI_MAGIC, 5)
#define Read_HPID_Auto _IO(HPI_MAGIC, 6)
#define Write_HPID _IO(HPI_MAGIC, 7)
#define Read_HPID _IO(HPI_MAGIC, 8)
#define Auto_HPID _IO(HPI_MAGIC, 9)
#define NoAuto_HPID _IO(HPI_MAGIC, 10)
#define Set_DSPINT _IO(HPI_MAGIC, 11)
#define Get_ball_found _IO(HPI_MAGIC, 12)
#define Get_ball_cy _IO(HPI_MAGIC, 13)
#define Get_ball_cx _IO(HPI_MAGIC, 14)
#define Disable_int _IO(HPI_MAGIC, 15)
#define Enable_int _IO(HPI_MAGIC, 16)
#define HPI_IOC_MAXNR 16
typedef struct hpi_device
{
int no_autoread;
int ball_found;
int ball_cy;
int ball_cx;
unsigned int buzy;
void * hpi_vbase;
char * HpiBaseBufRead;
char * HpiBaseBufWrite;
struct semaphore sem;
} HPI_DEV;
devfs_handle_t hpi_devfs;
HPI_DEV * hpi_dev;
int hpi_open (struct inode *inode, struct file *filp)
{
PDEBUG ("hpi device_open(%p,%p)/n", inode, filp);
if(hpi_dev->buzy)
{
printk("hpi device is in using/n");
return -1;
}
hpi_dev->buzy=1;
filp->private_data = hpi_dev;
MOD_INC_USE_COUNT;
enable_irq(HPI_INT);
return 0;
}
int hpi_release (struct inode *inode, struct file *filp)
{
disable_irq(HPI_INT);
MOD_DEC_USE_COUNT;
hpi_dev->buzy=0;
PDEBUG ("hpi device_release(%p,%p)/n", inode, filp);
return 0;
}
inline void HPIC_Write(u16 w)
{
unsigned char t1,t2;
t1 = (0xff00 & w) >>8;
t2 = (0x00ff & w);
outb(t1,hpi_dev->hpi_vbase+0x00);
outb(t2,hpi_dev->hpi_vbase+0x02);
}
inline u16 HPIC_Read(void)
{
unsigned char t1,t2;
t1=inb(hpi_dev->hpi_vbase+0x10);
t2=inb(hpi_dev->hpi_vbase+0x12);
return( (t1<<8) | t2);
}
inline void HPIA_Write(u16 w)
{
unsigned char t1,t2;
t1 = (0xff00 & w) >>8;
t2 = (0x00ff & w);
outb(t1,hpi_dev->hpi_vbase+0x04);
outb(t2,hpi_dev->hpi_vbase+0x06);
}
inline u16 HPIA_Read(void)
{
unsigned char t1,t2;
t1=inb(hpi_dev->hpi_vbase+0x14);
t2=inb(hpi_dev->hpi_vbase+0x16);
return( (t1<<8) | t2);
}
inline void HPID_AutoWrite(u16 w)
{
unsigned char t1,t2;
t1 = (0xff00 & w) >>8;
t2 = (0x00ff & w);
outb(t1,hpi_dev->hpi_vbase+0x08);
outb(t2,hpi_dev->hpi_vbase+0x0a);
}
inline u16 HPID_AutoRead(void)
{
unsigned char t1,t2;
t1=inb(hpi_dev->hpi_vbase+0x18);
t2=inb(hpi_dev->hpi_vbase+0x1a);
return( (t1<<8) | t2);
}
inline void HPID_Write(u16 w)
{
unsigned char t1,t2;
t1 = (0xff00 & w) >>8;
t2 = (0x00ff & w);
outb(t1,hpi_dev->hpi_vbase+0x0c);
outb(t2,hpi_dev->hpi_vbase+0x0e);
}
inline u16 HPID_Read(void)
{
unsigned char t1,t2;
t1=inb(hpi_dev->hpi_vbase+0x1c);
t2=inb(hpi_dev->hpi_vbase+0x1e);
return( (t1<<8) | t2);
}
inline void setdspint(void)
{
HPIC_Write(HPIC_Read() | 0x0404);
}
inline void clearhostint(void)
{
HPIC_Write(HPIC_Read() | 0x0808);
}
static void hpi_interrupt(int irq,void *dev_id,struct pt_regs *regs)
{
HPI_DEV *dev = dev_id;
HPIA_Write(0x0000);
dev->ball_found = HPID_AutoRead();
dev->ball_cy = HPID_AutoRead();
dev->ball_cx = HPID_AutoRead();
}
ssize_t hpi_read (struct file *filp, char *buf,size_t count,loff_t *oppos)
{
HPI_DEV *dev = filp->private_data;
int i;
size_t ret ;
if (dev->no_autoread) count=2;
dev->HpiBaseBufRead=kmalloc(count, GFP_KERNEL);
if (!dev->HpiBaseBufRead) return -ENOMEM;
if (down_interruptible (&dev->sem))
{
kfree(dev->HpiBaseBufRead);
return -ERESTARTSYS;
}
for(i=0;i {
if (dev->no_autoread)
((u16 *)dev->HpiBaseBufRead)[i]=HPID_Read();
else
((u16 *)dev->HpiBaseBufRead)[i]=HPID_AutoRead();
}
if(count%2) ((u8 *)dev->HpiBaseBufRead)[count]=(u8)(HPID_AutoRead() & 0x00ff);
ret=copy_to_user(buf,dev->HpiBaseBufRead,count)?-EFAULT : count;
up(&(dev->sem));
kfree(dev->HpiBaseBufRead);
return ret;
}
ssize_t hpi_write (struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{
HPI_DEV *dev = filp->private_data;
int i;
size_t ret;
if (dev->no_autoread) count=2;
dev->HpiBaseBufWrite=kmalloc(count, GFP_KERNEL);
if(!dev->HpiBaseBufWrite) return -ENOMEM;
down(&(dev->sem));
if(!copy_from_user(dev->HpiBaseBufWrite,buf,count))
{
for(i=0;i {
if (dev->no_autoread)
HPID_Write(((u16 *)dev->HpiBaseBufWrite)[i]);
else
HPID_AutoWrite(((u16 *)dev->HpiBaseBufWrite)[i]);
}
if(count%2) HPID_AutoWrite((u16)(0x0000 | dev->HpiBaseBufWrite[count]));
ret=count;
}
else
ret=-EFAULT;
up(&(dev->sem));
kfree(dev->HpiBaseBufWrite);
return ret;
}
int hpi_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
u16 val;
int ret;
HPI_DEV *dev = filp->private_data;
if (_IOC_TYPE(cmd) != HPI_MAGIC) return -ENOTTY;
if (_IOC_NR(cmd) > HPI_IOC_MAXNR) return -ENOTTY;
switch(cmd) {
case HPI_RESET:
HPIC_Write(0x1818);
HPIA_Write(0x0003);
HPIC_Write(0x0808);
HPIA_Write(0x0000);
hpi_dev->no_autoread=0;
break;
case Write_HPIC:
ret=get_user(val,(u16 *)arg);
if (ret) return ret;
HPIC_Write(val);
break;
case Read_HPIC:
val=HPIC_Read();
return put_user(val,(u16 *)arg);
case Write_HPIA:
ret=get_user(val,(u16 *)arg);
if (ret) return ret;
HPIA_Write(val);
break;
case Read_HPIA:
val=HPIA_Read();
return put_user(val,(u16 *)arg);
case Write_HPID_Auto:
ret=get_user(val,(u16 *)arg);
if (ret) return ret;
HPID_AutoWrite(val);
break;
case Read_HPID_Auto:
val=HPID_AutoRead();
return put_user(val,(u16 *)arg);
case Write_HPID:
ret=get_user(val,(u16 *)arg);
if (ret) return ret;
HPID_Write(val);
break;
case Read_HPID:
val=HPID_Read();
return put_user(val,(u16 *)arg);
case Auto_HPID:
hpi_dev->no_autoread=0;
break;
case NoAuto_HPID:
hpi_dev->no_autoread=1;
break;
case Set_DSPINT:
setdspint();
break;
case Get_ball_found:
return put_user(dev->ball_found,(u16 *)arg);
case Get_ball_cy:
return put_user(dev->ball_cy,(u16 *)arg);
case Get_ball_cx:
return put_user(dev->ball_cx,(u16 *)arg);
case Disable_int:
disable_irq(HPI_INT);
break;
case Enable_int:
enable_irq(HPI_INT);
break;
default:
return -ENOTTY;
}
return 0;
}
struct file_operations hpi_fops=
{
open : hpi_open,
release : hpi_release,
read : hpi_read,
ioctl : hpi_ioctl,
write : hpi_write,
};
int __init hpi_init(void)
{
PDEBUG("hpi_init/n");
hpi_devfs = devfs_register(NULL,"hpi",DEVFS_FL_DEFAULT,HPI_MAJOR,0,S_IFCHR |S_IRUSR |S_IWUSR |S_IRGRP |S_IWGRP,&hpi_fops,NULL);
if (NULL==hpi_devfs)
{
printk("hpi devfs_register failed/n");
goto fail_devfs_register;
}
PDEBUG("hpi devfs_register ok/n");
hpi_dev = kmalloc(sizeof (HPI_DEV), GFP_KERNEL);
if (NULL==hpi_dev)
{
printk("fail_malloc hpi_dev/n");
goto fail_malloc;
}
PDEBUG("hpi_dev kmalloc ok/n");
memset(hpi_dev, 0, sizeof (HPI_DEV));
sema_init (&hpi_dev->sem, 1);
hpi_dev->no_autoread=0;
hpi_dev->hpi_vbase=ioremap(HPI_BASEADDR,0x100);
PDEBUG("hpi_dev->hpi_vbase is %x/n",(unsigned int)hpi_dev->hpi_vbase);
if(NULL==request_region((unsigned int)hpi_dev->hpi_vbase,0x100,"hpi"))
{
printk("hpi request_region failed/n");
goto fail_request_region;
}
PDEBUG("hpi request_region ok/n");
set_external_irq(HPI_INT,EXT_FALLING_EDGE,GPIO_PULLUP_DIS);
if(0!=request_irq(HPI_INT,&hpi_interrupt,SA_SHIRQ,"hpi",hpi_dev))
{
printk("hpi request_irq failed/n");
goto fail_request_irq;
}
disable_irq(HPI_INT);
PDEBUG("hpi request_irq ok/n");
return 0;
fail_request_irq:
release_region((unsigned int)hpi_dev->hpi_vbase,0x100);
fail_request_region:
iounmap(hpi_dev->hpi_vbase);
kfree(hpi_dev);
fail_malloc:
devfs_unregister(hpi_devfs);
fail_devfs_register:
return -1;
}
void __exit hpi_exit(void)
{
PDEBUG("hpi exit/n");
free_irq(HPI_INT,hpi_dev);
release_region((unsigned int)hpi_dev->hpi_vbase,0x100);
iounmap(hpi_dev->hpi_vbase);
kfree(hpi_dev);
PDEBUG("hpi kfree ok/n");
devfs_unregister(hpi_devfs);
PDEBUG ("hpi cleanup/n");
}
module_init(hpi_init);
module_exit(hpi_exit);
MODULE_DESCRIPTION("Dsp hpi driver");
MODULE_AUTHOR("Dansen");
MODULE_LICENSE("GPL");
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮