📄 eibdrv.c
字号:
/* --------------------------------------------------------------------------- eibdrv.c --------------------------------------------------------------------------- eibdrv Version 0.2.1 Copyright (C) 2002, Wolfgang Tumfart Donaustrasse 104/9 A-2344 Maria Enzersdorf Austria (Europe) tumfart@auto.tuwien.ac.at This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --------------------------------------------------------------------------- */#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif#define VERSION_CODE(vers,rel,seq) (((vers)<<16) | ((rel)<<8) | (seq))// define FTSTATION_BCU2 if module is to be used// as BCU2 for test purposes#ifdef FTSTATION_BCU2# define FT_DIR 1#else# define FT_DIR 0#endif#include <linux/module.h>#include <linux/malloc.h>#include <linux/serial.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/smp_lock.h>#include <linux/mm.h>#include <linux/timer.h>#include <linux/tqueue.h>#include <linux/ioctl.h>#include <linux/delay.h>#include <asm/system.h>#include <asm/fcntl.h>#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)# include <linux/poll.h># include <asm/uaccess.h>#else # include <asm/segment.h>#endif#include "eibdrv.h"/* --------------------------------------------------------------------------- */#define EIBDRV_VERSION "0.2.1"#define EIBDRV_VERSION_CODE 513// Internal buffers/lists#define FT_PROC_BLOCKED 0x01 // write request of type acknowledged#define FT_PROC_NONBLOCKED 0x02 // write request of type non acknowledged#define FT_RMPROC_AUTO 0x01 // remove by server process#define FT_RMPROC_MAN 0x02 // remove by application process#define FT_PROC_FREE 0x04 // write request has been processed and // can be removed from the list#define FT_PROC_OPEN 0x08 // ==> rproc->flags // indicates that a slot of the read // process list is in use// FT1.2-protocol parameter#define FT_EXCHANGE_TIMEOUT 510 // time between request and ack (in bit)#define FT_LINE_IDLE_TIMEOUT 33 // time between two frames (in bit)#define FT_REPEAT_LIMIT 3 // number of transimissions of an // unacknowledged frame#define FT_FIXED_LENGTH_MSG 0x10 // start character of frame w fixed length#define FT_VAR_LENGTH_MSG 0x68 // start character of frame w variable length#define FT_ACK 0xE5 // acknowledge frame#define FT_FCB_VALID 0x01 // fcb valid/void depending on #define FT_FCB_VOID 0x00 // frame type#define FT_STATE_INIT 0 #define FT_STATE_READY 2 #define FT_STATE_WAIT_FOR_UDATA_ACK 3#define FT_STATE_WAIT_FOR_RESP_STATUS 4#define FT_STATE_WAIT_FOR_RESET_ACK 5#define FT_STATE_SHUTDOWN 9// Module method: Open, Release#define FT_SHARED_RW 0x00 // ==> ftstation.f_exclusive#define FT_EXCLUSIVE_RW 0x01 // indicates whether the FT1.2- // protocoll station is opened // for exclusive or shared // Read/Write acess./* --------------------------------------------------------------------------- */#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)static mm_segment_t fs;#elseunsigned long fs;# ifdef __ARCH_I386_POSIX_TYPES_Htypedef unsigned long suseconds_t;# endif#endif#if defined(__alpha__) # define count_t unsigned long# define read_write_t long#else# define count_t int# define read_write_t int#endifint c=0; // Numbering of messages ensures, that // all messages are display on the console/* =========================================================================== *//* FT-protocol station *//* =========================================================================== */char *port="/dev/ttyS1"; unsigned int major=100; int mode=FT_SERVERMODE; #if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)MODULE_PARM(port,"s");MODULE_PARM(major,"i");MODULE_PARM(mode,"i");#endifint baudrate=19200; int symb_baudrate=B19200; // lock variable for common ressourcestypedef struct sv { int val; struct wait_queue *wq; } sv; sv sv_ser_write={1,NULL}; // writing lock of serial interfacesv sv_ser_read ={1,NULL}; // reading lock of serial interfacesv sv_ready ={1,NULL}; // Initiating a new transmission cycle// Serial port used by the eibdrv driver to communicate via the// BCU2 with the EIB bus.typedef struct SerPort { struct file *filp; struct termios old_termios; struct tty_struct *tty; struct inode *inodp; } SerPort;// Structure containing all internal state variables and buffers of the // protocol station, that handles the communication with the BCU2 via // the FT1.2 protocol.typedef struct Eib_wpbuf Eib_wpbuf;typedef struct Eib_rpbuf Eib_rpbuf;typedef struct Eib_buf Eib_buf;typedef struct Eib_FTStation { int state; // state of the protocol automata int servproc; // server processes opened the device int servfunc; // server processes working int f_exclusive; // device opened exclusively int exchange_timeout; // max delay between request and answer (in jiffies) struct timeval exchange_time; // max delay between request and answer time_t line_idle_timeout_sec; // min delay betw to msg (in sec) suseconds_t line_idle_timeout_usec; // min delay betw two msg (in usec) struct timeval last_seract; // timestamp of last write/read access to tty struct timeval start_write; // timestamp of beginn of write struct timeval end_write; // timestamp of end of write w/o retransmissions int fcb; // fcb of next write message int rec_fcb; // fcb of last received message int wrepeat; // number of repetitions of write message int rrepeat; // number of retransmissions of read message SerPort port; // serial port Eib_statistics stat; // statistic information Eib_wpbuf *wpbuf; // buffer for write accesses Eib_rpbuf *rpbuf; // buffer for read accesses & received messges Eib_buf *outbuf; // buffer for write messages struct fasync_struct *pasync; // processes to be notified with SIGIO } Eib_FTStation;static Eib_FTStation ftstation; // protocol stationstruct wait_queue *wq_wproc=NULL; // blocking write processes in acknowledge // mode waiting for the result of // write accessstruct wait_queue *wq_rproc=NULL; // blocking read processes waiting for a // message from BCU2 in their bufferstruct wait_queue *wq_fullwproc=NULL; // blocking write processes in standard // mode waiting for an empty slot in // outbuf and wpbufstruct wait_queue *wq_ser_write=NULL; // serial interface write process // waits for new data in outbufstruct wait_queue *wq_wait_for_ack=NULL; // ser_write waits for ack or // exchange timeout struct wait_queue *wq_shutdown=NULL; // cleanup_module waits for idle_read // and idle_write to notify their closure // by decrementing ftstation.servproc struct wait_queue *sleep_queue=NULL;/* =========================================================================== *//* Message buffer *//* =========================================================================== */ /* If the module is installed in server mode, buffers are used for both outgoing and incoming messages. They are implemented as ring buffer with a maximum message length of EIB_BUF_ELEMENT_SIZE unsigned characters. */ struct Eib_buf { unsigned char *mem; // start of memory region for slots unsigned char *next_read; // slot containing next message to be read unsigned char *next_write; // slot for next message to be written unsigned long count; // number of messages in buffer unsigned long size; // number of available slots in buffer }; /* This function allocates the memory for a message buffer of size elements, each with a maximum length of EIB_BUF_ELEMENT_SIZE characters, according to the maximum message length specified for the FT1.2-protocol in the EIB system. The function returns a pointer to the buffer, which is used as parameter for all other function calls regarding the message buffer, or NULL, if the necessary memory could not be allocated. */Eib_buf *eib_get_buf(unsigned long size); /* This function deallocates the memory used for a message buffer and has to be called if the buffer is not longer to be used. */void eib_return_buf(Eib_buf *buf); /* This function returns the oldest unread message in the buffer; the read pointer is set to the next unread message. The argument element points to a preallocated array of type unsigned character, into which the message is copied. It is safe to choose the size of the array not shorter than EIB_BUF_ELEMENT_SIZE. The length of the message is returned in the function value. */int eib_read_buf(Eib_buf *buf,unsigned char *element); /* This function copies len characters (maximum is EIB_BUF_ELEMENT_SIZE) from element into a slot of the message buffer. The function returns -ENOBUFS, if all slots of the message buffer are filled, or 0 otherwise. */int eib_write_buf(Eib_buf *buf,unsigned char *element,int len); /* This function resizes the buffer to new_size. It returns -ENOMEM, if memory cannot be allocated for the new buffer; -ESIZE, if the new list is too small to hold all entries of the old list and resizing is therefore rejected; or 0 otherwise. */ int eib_resize_buf(Eib_buf **buf,unsigned long new_size);unsigned long eib_get_buf_count(Eib_buf *buf);unsigned long eib_get_buf_size(Eib_buf *buf);void eib_display_buf(Eib_buf *buf);// for internal use onlyvoid eib_init_buf(Eib_buf *buf);void eib_calc_nextpos_buf(Eib_buf *buf,unsigned char **nextpos);void eib_copymem_buf(Eib_buf *old_buf,Eib_buf *new_buf);/* =========================================================================== *//* List of write processes *//* =========================================================================== *//* References to all write processes (blocking and nonblocking) are kept in an ordered list until the write access has been achknowledged by the BCU2 or the write access has been unsuccessfull for a certain number of repetitions. */unsigned long wpbuf_size=20; unsigned long outbuf_size=10; #if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)MODULE_PARM(wpbuf_size,"l");MODULE_PARM(outbuf_size,"l");#endiftypedef struct Eib_wproc { pid_t pid; // id of write process int flags; // remove and processed-flag, 0 if empty slot int result; // -EAGAIN if write unsuccessful, 0..23 else unsigned long next; // index 1..wpbuf_size of next process unsigned long prev; // index 1.. wpbuf_size of previous process } Eib_wproc; struct Eib_wpbuf { struct Eib_wproc *mem; // start of memory region for slots unsigned long first; // index 1..wpbuf_size of first slot unsigned long last; // index 1..wpbuf_size of last slot unsigned long next_result; // index of slot, where next result to write unsigned long count; // number of processes in list unsigned long size; // number of available slots in buffer }; /* This function allocates memory for a process list of size elements (slots). The function returns a pointer to the buffer, which is used as parameter for all other function calls regarding the process list, or NULL, if the necessary memory could not be allocated. */Eib_wpbuf *eib_get_wpbuf(unsigned long size); /* This function deallocates the memory used for a process list and has to be called if the process list is not longer to be used. */void eib_return_wpbuf(Eib_wpbuf *buf); /* This function sets a process with the process-id pid into the process list. flags indicates whether the process is in blocking (FT_PROC_BLOCKED) or nonblocking (FT_PROC_NONBLOCKED) write mode. The function returns -ENOBUFS, if no empty slot in the process list is available, or 0 otherwise. */ int eib_write_wpbuf(Eib_wpbuf *buf,pid_t pid,int flags); /* This function returns the result of a write process and removes it from the list. The function returns -ENOPROC, if the process with the given id is not in the process list; -ENORESULT, if the write access has not been processed yet and can therefore not be removed from the list; or the number of written and acknowledged characters by the BCU2. */int eib_condrm_wpbuf(Eib_wpbuf *buf,pid_t pid); /* This function stores the result of a write access in the appropriate slot in the process list. */ void eib_result_wpbuf(Eib_wpbuf *buf,int result); /* This function resizes the process list to new_size. It returns -ENOMEM, if memory cannot be allocated for the new list; -ESIZE, if the new list is too small to hold all entries of the old list, and resizing is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -