⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diopsis.c

📁 Linux 核心驱动程序。提供多线程访问和保护能力。快速I/O访问。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Sean Haycock 26/03/2009Char device Driver 'diopsis' to load module and indicate to a user application when a genlock pulse has arrived at the ioport 'genlock'. This will trigger aninterrupt which will call kill_fasync() to send SIGIO to the application thatmust catch the SIGIO with the command signal(). This will indicate to the applicationto read the encoder data from the device.16/04/2009   SH   added - mmap function so that user can access data in enc_buf30/04/2009   SH   added - actually encoder ioports*/#include <linux/init.h>#include <linux/module.h>#include <linux/version.h>#include <linux/kernel.h>        /* printk() */#include <linux/slab.h>          /* kmalloc() */#include <linux/fs.h>            /* everything... */#include <linux/errno.h>         /* error codes */#include <linux/types.h>         /* size_t */#include <linux/fcntl.h>         /* O_ACCMODE */#include <asm/system.h>          /* cli(), *_flags */#include <asm/uaccess.h>         /* copy_from/to_user */#include <linux/interrupt.h>     /* interrupt headers */#include <linux/signal.h>        /*interrupt arguments */#include <linux/ioport.h>        /* allocating io ports */#include <linux/socket.h>#include <asm/semaphore.h>     /* mutex */#include <linux/delay.h>         /* delay to test read blocking */#include <linux/cdev.h>#include <linux/mm.h>#include <asm/io.h>#define SA_INTERRUPT 0            /* declares 'fast interrupt' */#define SUCCESS 0                 /* return value */#define MEM_SIZE 100#define PORT_SIZE 1               /* size of io port */#define LEN 16/* Definitions for MESA encoder 4I36 board */ #define BASE                 0x220#define MESA_INDEX_OFFSET    0x00#define MSA_COUNTLO_OFFSET   0x02#define MSA_COUNTHI_OFFSET   0x04#define IDXAutoInc_bit       0x4000MODULE_AUTHOR("Sean Haycock");MODULE_DESCRIPTION("Char device driver for diopsis board"); MODULE_LICENSE("Dual BSD/GPL"); /* Declarations of functions */int diopsis_open(struct inode *inode, struct file *filp);                        int diopsis_release(struct inode *inode, struct file *filp);                     ssize_t diopsis_read(struct file *filp, char *buf, size_t count, loff_t *f_pos); ssize_t diopsis_write(struct file *filp, char *buf, size_t count, loff_t *f_pos);int diopsis_init(void);                                                          /* intialise */void diopsis_exit(void);                                                         /* clean up */static irqreturn_t diopsis_interrupt(int irq, void *dev_id, struct pt_regs *regs);/*interrupt */static int dev_fasync(int fd, struct file *filp, int on);      /* user space communication*/static int diopsis_mmap(struct file *filp, struct vm_area_struct *vma);/* prototype for mapping each encoder buffers pages for shared memory */static int diopsis_mmap_c0(struct file *filp, struct vm_area_struct *vma);static int diopsis_mmap_c1(struct file *filp, struct vm_area_struct *vma);static int diopsis_mmap_c2(struct file *filp, struct vm_area_struct *vma);static int diopsis_mmap_c3(struct file *filp, struct vm_area_struct *vma);/* Module init and exit declarations */module_init(diopsis_init);                              /* installs modules */module_exit(diopsis_exit);                              /* uninstalls module */ /* file operations for driver */struct file_operations diopsis_fops = {  .owner = THIS_MODULE,              /* prevents module from being unloaded whilst in use */  .read = diopsis_read,              /* read function*/  .write = diopsis_write,            /* write function */  .open = diopsis_open,              /* open function*/  .release = diopsis_release,        /* release function*/  .fasync = dev_fasync,              /* to notify device of change in FASYNC flag */  .mmap = diopsis_mmap,		     /* memory map */};static struct fasync_struct *dev_async_queue;struct semaphore sem, sem2;/* MESA board address offsets */int index    = BASE + MESA_INDEX_OFFSET;        /* index register */int countLow = BASE + MSA_COUNTLO_OFFSET;       /* counter low register */int countHigh= BASE + MSA_COUNTHI_OFFSET;       /* counter high register *//* Global variables */int diopsis_major   = 111;     /* Major number */ int diopsis_irq     = 15;      /* interrupt number */int gen_port        = 0x400;   /* Genlock io port 0xXXX */int index_reg       = 0x220;   /* Index register on MESA board */int counterlow_reg  = 0x222;   /* counter low register on MESA board */int counterhigh_reg = 0x224;   /* counter high register on MESA board */int gen_io;                    /* check genlock ioport return value */int enc_io;                    /* check encoder ioport return value *///int interrupt_cnt=0;             /* counts number of interrupts -for TEST purpos*///int read_cnt=0;                  /* counts number of reads- for TEST purpose *//* input data values from MESA board encoder channels */int enc_0_hi, enc_0_lo;        /* channel 0 upper and lower word values */int enc_1_hi, enc_1_lo;        /* channel 1 upper and lower word values */int enc_2_hi, enc_2_lo;        /* channel 2 upper and lower word values */int enc_3_hi, enc_3_lo;        /* channel 3 upper and lower word values */ /*-------------------------------------------- |   pointers to each encoder buffer data    | -------------------------------------------- */    /* encoder bit 0 buffer pointer */    int *enc_buf_0;		           /* kmalloc pointer */    static int *kmalloc_area_0;            /* rounded up page boundry pointer of kmalloc */      /* encoder bit 1 buffer pointer */    int *enc_buf_1;    static int *kmalloc_area_1;    /* encoder bit 2 buffer pointer */    int *enc_buf_2;    static int *kmalloc_area_2;    /* encoder bit 3 buffer pointer */    int *enc_buf_3;    static int *kmalloc_area_3;  /*----------------------------------------------------*/   /*---------------------------------------------------------    |            Page Memory Mapping for Encoder Buffers     |    ----------------------------------------------------------*//* memory mapping function */static int diopsis_mmap(struct file *filp, struct vm_area_struct *vma){    if(vma->vm_pgoff == 0)                     /* offset of 0 */    {        return diopsis_mmap_c0(filp,vma);    }    if(vma->vm_pgoff == LEN)                   /* offset of 16 */    {        return diopsis_mmap_c1(filp,vma);    }    if(vma->vm_pgoff == 2*LEN)                 /* offset of 32 */    {        return diopsis_mmap_c2(filp,vma);    }    if(vma->vm_pgoff == 3*LEN)                 /* offset of 48 */    {        return diopsis_mmap_c3(filp,vma);    }}/* ----------encoder channel 0 buffer page mapping-------------------*/static int diopsis_mmap_c0(struct file *filp, struct vm_area_struct *vma){    int ret;    long length = vma->vm_end - vma->vm_start;    printk(KERN_INFO "mmap function c0\n");        ret = remap_pfn_range(vma,		          vma->vm_start,                          virt_to_phys((void *)kmalloc_area_0) >> PAGE_SHIFT,                          length,                          vma->vm_page_prot);    return 0;}/* ----------encoder channel 1 buffer page mapping-------------------*/static int diopsis_mmap_c1(struct file *filp, struct vm_area_struct *vma){    int ret;    long length = vma->vm_end - vma->vm_start;    printk(KERN_INFO "mmap function c1\n");        ret = remap_pfn_range(vma,		          vma->vm_start,                          virt_to_phys((void *)kmalloc_area_1) >> PAGE_SHIFT,                          length,                          vma->vm_page_prot);    return 0;}/* ----------encoder channel 2 buffer page mapping-------------------*/static int diopsis_mmap_c2(struct file *filp, struct vm_area_struct *vma){    int ret;    long length = vma->vm_end - vma->vm_start;    printk(KERN_INFO "mmap function c2\n");        ret = remap_pfn_range(vma,		          vma->vm_start,                          virt_to_phys((void *)kmalloc_area_2) >> PAGE_SHIFT,                          length,                          vma->vm_page_prot);    return 0;}/* ----------encoder channel 3 buffer page mapping-------------------*/static int diopsis_mmap_c3(struct file *filp, struct vm_area_struct *vma){    int ret;    long length = vma->vm_end - vma->vm_start;    printk(KERN_INFO "mmap function c3\n");        ret = remap_pfn_range(vma,		          vma->vm_start,                          virt_to_phys((void *)kmalloc_area_3) >> PAGE_SHIFT,                          length,                          vma->vm_page_prot);    return 0;}/*-------------------------------------------------------------*//* initialisation */int diopsis_init(void) {   int result;   int irq_result;   int i;     printk(KERN_INFO "Inserting diopsis module\n");     /* Registering device */  result = register_chrdev(diopsis_major, "diopsis", &diopsis_fops);  printk(KERN_INFO "Diopsis register with major number: %d\n", diopsis_major);  if (result < 0)   {    printk(KERN_INFO "Diopsis: cannot obtain major number %d\n", diopsis_major);    return result;  }  /* Requesting interrupt for device      interrupt can be seen by cat /proc/interrupts */  irq_result = request_irq(diopsis_irq, diopsis_interrupt, SA_INTERRUPT, "genlock", NULL);  printk(KERN_INFO "Diopsis interrupt: %d\n", diopsis_irq);  if(irq_result)  {           printk(KERN_INFO "Genlock: can't get assigned irq: %d\n", diopsis_irq);  }  /*------------------------------------------------------   |       ALLOCATING IO PORTS FOR ENCODER DATA          |   |-----------------------------------------------------|   | i)  check to see if io region is free               |   | ii) allocate io region if free                      |   ------------------------------------------------------*//*---------- allocationg io port for genlock -----------*/  gen_io = check_region(gen_port, PORT_SIZE);           /* check if region is free? */  if(gen_io)  {        printk(KERN_INFO "cannot reserve genlock io: %x\n", gen_port);  }  request_region(gen_port, PORT_SIZE, "genlock");       /* allocate io region for genlock *//* ---------allocationg io port for MESA index register channel -------*/  enc_io = check_region(index_reg, PORT_SIZE);         /* check if region is free? */  if(enc_io)  {        printk(KERN_INFO "cannot reserve encoder io: %x\n", index_reg);  }  request_region(index_reg, PORT_SIZE, "mesa_index");  /* allocate io region for encoder *//* --------allocationg io port for MESA counter low register ----------*/  enc_io = check_region(counterlow_reg, PORT_SIZE);         /* check if region is free? */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -