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

📄 n_r3964.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
/* r3964 linediscipline for linux * * ----------------------------------------------------------- * Copyright by  * Philips Automation Projects * Kassel (Germany) * http://www.pap-philips.de * ----------------------------------------------------------- * This software may be used and distributed according to the terms of * the GNU General Public License, incorporated herein by reference. * * Author: * L. Haag * * $Log: n_r3964.c,v $ * Revision 1.8  2000/03/23 14:14:54  dwmw2 * Fix race in sleeping in r3964_read() * * Revision 1.7  1999/28/08 11:41:50  dwmw2 * Port to 2.3 kernel * * Revision 1.6  1998/09/30 00:40:40  dwmw2 * Fixed compilation on 2.0.x kernels * Updated to newly registered tty-ldisc number 9 * * Revision 1.5  1998/09/04 21:57:36  dwmw2 * Signal handling bug fixes, port to 2.1.x. * * Revision 1.4  1998/04/02 20:26:59  lhaag * select, blocking, ... * * Revision 1.3  1998/02/12 18:58:43  root * fixed some memory leaks * calculation of checksum characters * * Revision 1.2  1998/02/07 13:03:34  root * ioctl read_telegram * * Revision 1.1  1998/02/06 19:21:03  root * Initial revision * * */#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/slab.h>#include <linux/tty.h>#include <linux/errno.h>#include <linux/string.h>   /* used in new tty drivers */#include <linux/signal.h>   /* used in new tty drivers */#include <linux/ioctl.h>#include <linux/n_r3964.h>#include <linux/poll.h>#include <linux/init.h>#include <asm/uaccess.h>//#define DEBUG_QUEUE/* Log successful handshake and protocol operations  *///#define DEBUG_PROTO_S/* Log handshake and protocol errors: *///#define DEBUG_PROTO_E/* Log Linediscipline operations (open, close, read, write...): *///#define DEBUG_LDISC/* Log module and memory operations (init, cleanup; kmalloc, kfree): *///#define DEBUG_MODUL/* Macro helpers for debug output: */#define TRACE(format, args...) printk("r3964: " format "\n" , ## args);#ifdef DEBUG_MODUL#define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args);#else#define TRACE_M(fmt, arg...) /**/#endif#ifdef DEBUG_PROTO_S#define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args);#else#define TRACE_PS(fmt, arg...) /**/#endif#ifdef DEBUG_PROTO_E#define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args);#else#define TRACE_PE(fmt, arg...) /**/#endif#ifdef DEBUG_LDISC#define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args);#else#define TRACE_L(fmt, arg...) /**/#endif#ifdef DEBUG_QUEUE#define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args);#else#define TRACE_Q(fmt, arg...) /**/#endifstatic void on_timer_1(void*);static void on_timer_2(void*);static void add_tx_queue(struct r3964_info *, struct r3964_block_header *);static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code);static void put_char(struct r3964_info *pInfo, unsigned char ch);static void trigger_transmit(struct r3964_info *pInfo);static void retry_transmit(struct r3964_info *pInfo);static void transmit_block(struct r3964_info *pInfo);static void receive_char(struct r3964_info *pInfo, const unsigned char c);static void receive_error(struct r3964_info *pInfo, const char flag);static void on_timeout(struct r3964_info *pInfo);static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg);static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char *buf);static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,             int error_code, struct r3964_block_header *pBlock);static struct r3964_message* remove_msg(struct r3964_info *pInfo,              struct r3964_client_info *pClient);static void remove_client_block(struct r3964_info *pInfo,                 struct r3964_client_info *pClient);static int  r3964_open(struct tty_struct *tty);static void r3964_close(struct tty_struct *tty);static ssize_t r3964_read(struct tty_struct *tty, struct file *file,                     unsigned char *buf, size_t nr);static ssize_t r3964_write(struct tty_struct * tty, struct file * file,                      const unsigned char * buf, size_t nr);static int r3964_ioctl(struct tty_struct * tty, struct file * file,                       unsigned int cmd, unsigned long arg);static void r3964_set_termios(struct tty_struct *tty, struct termios * old);static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,		      struct poll_table_struct  *wait);static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,                              char *fp, int count);static int  r3964_receive_room(struct tty_struct *tty);static struct tty_ldisc tty_ldisc_N_R3964 = {        TTY_LDISC_MAGIC,       /* magic */	"R3964",               /* name */        0,                     /* num */        0,                     /* flags */        r3964_open,            /* open */        r3964_close,           /* close */        0,                     /* flush_buffer */        0,                     /* chars_in_buffer */        r3964_read,            /* read */        r3964_write,           /* write */        r3964_ioctl,           /* ioctl */        r3964_set_termios,     /* set_termios */        r3964_poll,            /* poll */                    r3964_receive_buf,     /* receive_buf */        r3964_receive_room,    /* receive_room */        0                      /* write_wakeup */};static void dump_block(const unsigned char *block, unsigned int length){   unsigned int i,j;   char linebuf[16*3+1];      for(i=0;i<length;i+=16)   {      for(j=0;(j<16) && (j+i<length);j++)      {         sprintf(linebuf+3*j,"%02x ",block[i+j]);      }      linebuf[3*j]='\0';      TRACE_PS("%s",linebuf);   }}         /************************************************************* * Driver initialisation *************************************************************//************************************************************* * Module support routines *************************************************************/static void __exit r3964_exit(void){   int status;      TRACE_M ("cleanup_module()");   status=tty_register_ldisc(N_R3964, NULL);      if(status!=0)   {      printk(KERN_ERR "r3964: error unregistering linediscipline: %d\n", status);   }   else   {      TRACE_L("linediscipline successfully unregistered");   }   }static int __init r3964_init(void){   int status;      printk ("r3964: Philips r3964 Driver $Revision: 1.8 $\n");   /*    * Register the tty line discipline    */      status = tty_register_ldisc (N_R3964, &tty_ldisc_N_R3964);   if (status == 0)     {       TRACE_L("line discipline %d registered", N_R3964);       TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags,                tty_ldisc_N_R3964.num);       TRACE_L("open=%x", (int)tty_ldisc_N_R3964.open);       TRACE_L("tty_ldisc_N_R3964 = %x", (int)&tty_ldisc_N_R3964);     }   else     {       printk (KERN_ERR "r3964: error registering line discipline: %d\n", status);     }   return status;}module_init(r3964_init);module_exit(r3964_exit);/************************************************************* * Protocol implementation routines *************************************************************/static void on_timer_1(void *arg){   struct r3964_info *pInfo = (struct r3964_info *)arg;     if(pInfo->count_down)   {      if(!--pInfo->count_down)      {         on_timeout(pInfo);      }   }   queue_task(&pInfo->bh_2, &tq_timer);}static void on_timer_2(void *arg){   struct r3964_info *pInfo = (struct r3964_info *)arg;     if(pInfo->count_down)   {      if(!--pInfo->count_down)      {         on_timeout(pInfo);      }   }   queue_task(&pInfo->bh_1, &tq_timer);}static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader){   unsigned long flags;      save_flags(flags);   cli();   pHeader->next = NULL;   if(pInfo->tx_last == NULL)   {      pInfo->tx_first = pInfo->tx_last = pHeader;   }   else   {      pInfo->tx_last->next = pHeader;      pInfo->tx_last = pHeader;   }      restore_flags(flags);   TRACE_Q("add_tx_queue %x, length %d, tx_first = %x",           (int)pHeader, pHeader->length, (int)pInfo->tx_first );}static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code){   struct r3964_block_header *pHeader;   unsigned long flags;#ifdef DEBUG_QUEUE   struct r3964_block_header *pDump;#endif      pHeader = pInfo->tx_first;   if(pHeader==NULL)      return;#ifdef DEBUG_QUEUE   printk("r3964: remove_from_tx_queue: %x, length %d - ",          (int)pHeader, (int)pHeader->length );   for(pDump=pHeader;pDump;pDump=pDump->next)	 printk("%x ", (int)pDump);   printk("\n");#endif   if(pHeader->owner)   {      if(error_code)      {          add_msg(pHeader->owner, R3964_MSG_ACK, 0,                   error_code, NULL);      }      else      {          add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length,                   error_code, NULL);      }      wake_up_interruptible (&pInfo->read_wait);   }   save_flags(flags);   cli();   pInfo->tx_first = pHeader->next;   if(pInfo->tx_first==NULL)   {      pInfo->tx_last = NULL;   }   restore_flags(flags);   kfree(pHeader);   TRACE_M("remove_from_tx_queue - kfree %x",(int)pHeader);   TRACE_Q("remove_from_tx_queue: tx_first = %x, tx_last = %x",          (int)pInfo->tx_first, (int)pInfo->tx_last );}static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader){   unsigned long flags;      save_flags(flags);   cli();   pHeader->next = NULL;   if(pInfo->rx_last == NULL)   {      pInfo->rx_first = pInfo->rx_last = pHeader;   }   else   {      pInfo->rx_last->next = pHeader;      pInfo->rx_last = pHeader;   }   pInfo->blocks_in_rx_queue++;      restore_flags(flags);   TRACE_Q("add_rx_queue: %x, length = %d, rx_first = %x, count = %d",          (int)pHeader, pHeader->length,          (int)pInfo->rx_first, pInfo->blocks_in_rx_queue);}static void remove_from_rx_queue(struct r3964_info *pInfo,                 struct r3964_block_header *pHeader){   unsigned long flags;   struct r3964_block_header *pFind;      if(pHeader==NULL)      return;   TRACE_Q("remove_from_rx_queue: rx_first = %x, rx_last = %x, count = %d",          (int)pInfo->rx_first, (int)pInfo->rx_last, pInfo->blocks_in_rx_queue );   TRACE_Q("remove_from_rx_queue: %x, length %d",          (int)pHeader, (int)pHeader->length );   save_flags(flags);   cli();   if(pInfo->rx_first == pHeader)   {      /* Remove the first block in the linked list: */      pInfo->rx_first = pHeader->next;            if(pInfo->rx_first==NULL)      {         pInfo->rx_last = NULL;      }      pInfo->blocks_in_rx_queue--;   }   else    {      /* Find block to remove: */      for(pFind=pInfo->rx_first; pFind; pFind=pFind->next)      {         if(pFind->next == pHeader)          {            /* Got it. */            pFind->next = pHeader->next;            pInfo->blocks_in_rx_queue--;            if(pFind->next==NULL)            {               /* Oh, removed the last one! */               pInfo->rx_last = pFind;            }            break;         }      }   }   restore_flags(flags);   kfree(pHeader);   TRACE_M("remove_from_rx_queue - kfree %x",(int)pHeader);   TRACE_Q("remove_from_rx_queue: rx_first = %x, rx_last = %x, count = %d",          (int)pInfo->rx_first, (int)pInfo->rx_last, pInfo->blocks_in_rx_queue );}static void put_char(struct r3964_info *pInfo, unsigned char ch){   struct tty_struct *tty = pInfo->tty;   if(tty==NULL)      return;   if(tty->driver.put_char)   {      tty->driver.put_char(tty, ch);   }   pInfo->bcc ^= ch;}static void flush(struct r3964_info *pInfo){   struct tty_struct *tty = pInfo->tty;   if(tty==NULL)      return;   if(tty->driver.flush_chars)   {      tty->driver.flush_chars(tty);   }}static void trigger_transmit(struct r3964_info *pInfo){   unsigned long flags;      save_flags(flags);   cli();   if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL))   {      pInfo->state = R3964_TX_REQUEST;      pInfo->count_down = R3964_TO_QVZ;      pInfo->nRetry=0;      pInfo->flags &= ~R3964_ERROR;            restore_flags(flags);      TRACE_PS("trigger_transmit - sent STX");      put_char(pInfo, STX);      flush(pInfo);      pInfo->bcc = 0;   }   else   {

⌨️ 快捷键说明

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