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

📄 tid_driver.c

📁 mpc8xx driver(led), based on tqm8
💻 C
字号:
/*********************************************************************** * * (C) Copyright 2000 * Jean-Jacques Germond, Fr閐閞ic Soulier, Christian Batt; Alcatel * C/O jjg@sxb.bsf.alcatel.fr * * All rights reserved. * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU *Library* General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * *Library* General Public License for more details. * * You should have received a copy of the GNU *Library* General Public * License along with this program (see file COPYING.LIB); if not, * write to the Free Software Foundation, Inc., 675 Mass Ave, * Cambridge, MA 02139, USA. * ***********************************************************************//* The "trivial interrupt driver" main file  */#include "tid_def.h"#include <asm/init.h>		/* for __initfunc		*/#include <asm/fcntl.h>#include <asm/uaccess.h>	/* for put_user			*//* * Module Parameters - settable with "insmod" or "LILO" etc. * * Timer period (in us) */#define	TID_DEFAULT_PERIOD	1000000		/* default: 1 second */static unsigned int period = TID_DEFAULT_PERIOD;#ifdef	MODULEMODULE_PARM(period,"i");#endif	/* MODULE *//* The module structure */static struct module __this_module;/* The static descriptor for the unique tid device */Tid_Dev  tid_dev_struct;    static loff_ttid_lseek (struct file *filp, loff_t off, int whence){  Tid_Dev *dev = &tid_dev_struct;  long newpos;  switch(whence) {  case 0: /* SEEK_SET */    newpos = off;    break;  case 1: /* SEEK_CUR */    newpos = filp->f_pos + off;    break;  case 2: /* SEEK_END */    newpos = dev->nbChars + off;    break;  default: /* can't happen */    return -EINVAL;  }  if (newpos < 0) {    return -EINVAL;  }  filp->f_pos = newpos;  return newpos;}/* * Data management: read and write */    static ssize_ttid_read (struct file *filp, char *buf, size_t count, loff_t* ppos){  int      result;                             /* work */  int      i;                                  /* work */  loff_t   start_pos;                          /* f_pos upon entry */  ssize_t  copyLen;                            /* The signed copy length */  Tid_Dev *dev = &tid_dev_struct;              /* The device descriptor */  /* Can't seek (pread) on tid devices.  */  if (ppos != &filp->f_pos) return -ESPIPE;  /* Error if the file has been reseted by some other process */  if (dev->uniqueId != (long)filp->private_data) {    return -EIO;  }  start_pos = filp->f_pos;  if (start_pos > dev->nbChars) {    return 0;           /* EOF return (probably due to some far-away seek) */  }  if (start_pos >= dev->maxChars) {    return 0;           /* EOF return (OK if == maxChars) */  }  if (start_pos == dev->nbChars) {    /* Put this process to wait into the tid wait queue */    result = tid_wait(start_pos);    if (result < 0) {      return result;   /* The process was signaled or some error occured */    }  }  /* Truncate as appropriate (not sure how to handle negative counts */  copyLen = dev->nbChars - start_pos;         /* What we can copy */  if (copyLen > count) copyLen = count;       /* What we will copy */  if (copyLen < 0) {    /* We should never be here.  But beter be safe than sorry... */    return -EIO;  }  for (i = 0 ; i < copyLen; i++) {    result = copy_to_user(buf++, tid_ripple(start_pos + i), 1);    if (result < 0) return result;    /* Copy failed */  }  filp->f_pos += copyLen;  return copyLen;}    static ssize_ttid_write (struct file *filp, const char *buf, size_t count, loff_t* ppos)     /* The semantic of write is : reset the virtual device */{  /* Can't seek (pread) on trivial devices.  */  if (ppos != &filp->f_pos) return -ESPIPE;  if (tid_useSimulatedTimer()) {    tid_simu_timer_interrupt(count);       /* Simulate count interrupts */  }  filp->f_pos += count;                    /* Useless ??? */  return count;}    static inttid_ioctl (struct inode* inode, struct file *filp,	          unsigned int cmd, unsigned long arg){  return 0;}    static inttid_open (struct inode* inode, struct file *filp){  unsigned int flags;                      /* Open flags  */  Tid_Dev *dev = &tid_dev_struct;              /* The device descriptor */  /* Process the access flags */  filp->f_pos = 0;                   /* Setup the default position */  flags = (filp->f_flags) & (O_RDONLY | O_WRONLY | O_RDWR);  switch (flags) {  case O_RDONLY:    break;  case O_WRONLY:  case O_RDWR:            /* For our trivial cse, this is same as O_WRONLY */    if ( (filp->f_flags & O_APPEND) == 0) {      dev->uniqueId += 1; /* The # of resets  */      dev->nbChars = 0;   /* Raz previous content if any */      /* At this point we should wake up processes that are waiting on       * the 'previous instance'.  But this is too complex to begin with       * and we wont test this case yet.  See note in trv_def.h.       */    } else {      filp->f_pos = dev->nbChars;   /* Append at end of file */    }    break;  default:                          /* Invalid access flags */    return -EINVAL;  }  filp->private_data = (void*)dev->uniqueId;   /* The device instance # */  MOD_INC_USE_COUNT;  return 0;           /* OK return */}    static inttid_flush (struct file *filp){    MOD_DEC_USE_COUNT;    return 0;}/* * The different file operations */struct file_operations tid_fops = {    tid_lseek,    tid_read,    tid_write,    NULL,          /* tid_readdir */    NULL,          /* tid_select */    tid_ioctl,    NULL,          /* tid_mmap */    tid_open,    tid_flush,                   /* nothing more, fill with NULLs */};/* The driver init function: we use statically allocated Major/Minor * numbers because dynamic allocation (AR pg: 44) is too expensive * in our embedded environment. */__initfunc ( int tid_init(void) ){  int result;		/* Result from kernel calls */  /* Init the tid device */  Tid_Dev* dev = &tid_dev_struct;  dev->nbChars    = 0;                     /* The # of char in the device	*/  dev->uniqueId   = 0;                     /* The # of resets			*/  dev->maxChars   = tid_rippleInit() * 20; /* Max size of the virtual device	*/     /* Items that are only used for debug and display in /proc */  dev->nbIntrEver = 0;                     /* # of interrupts since init	*/  dev->nbBhActiv  = 0;                     /* # of bh activations since init	*/  dev->nbWakeUp   = 0;                     /* # of wakeups for UNIX proc.	*/  dev->lastWakeup = -1;                    /* Code of last wakeup		*/  dev->hw	  = (void *)0;		   /* hardware specific data		*/  /* Register our major */  result = register_chrdev(TID_MAJOR, "tid", &tid_fops);  if (result < 0) {    printk(KERN_WARNING "tid: can't register %d\n", TID_MAJOR);    return result;  }  /* Register the trivial driver into /proc */  result = tid_proc_register();  if (result) {    goto registerProcFails;  }  /* Do the hw and foreground inits */  result = tid_connect_timer(dev, period);  if (result) {    printk(KERN_WARNING  "tid: can't init the timer error=%d\n", result);    goto connectTimerFails;  }  return 0;                  /* Succeed */connectTimerFails:  tid_proc_unregister();registerProcFails:  unregister_chrdev(TID_MAJOR, "tid");  return result;}/* * Provide module initialization and de-initialization when compiled as module. */#ifdef	MODULEint init_module(void){  return tid_init();}void cleanup_module(void){  /* Init the tid device */  Tid_Dev* dev = &tid_dev_struct;  tid_disconnect_timer (dev);  unregister_chrdev(TID_MAJOR, "tid");  /* Get out of /proc */  tid_proc_unregister();}#endif	/* MODULE */

⌨️ 快捷键说明

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