DSP

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");