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

📄 write.c

📁 HMS30C7202下的CAN驱动
💻 C
字号:
/* write.c * * Written by Sebastian Stolzenberg email:stolzi@sebastian-stolzenberg.de * Version 1.0  04 Feb 2003 */#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif#define EXPORT_SYMTAB#include "../include/candrv.h"#include "../include/hms30c7202_can.h"#include "../include/c_can.h"// Prototypesstatic inline u16 txspacefree( struct msgobj_t *pmsgobj );////////////////////////////////////////////////////////////////////////////////* * can_write * * Write function called by user through device file. */ssize_t can_write( struct file *filp,                   const char *buffer,                   size_t length,                   loff_t *offset ){        struct msgobj_t *pmsgobj = NULL;        unsigned long irqflags;        int written = 0;        u16 bytes_to_copy = 0;        if ( offset != &filp->f_pos) return -ESPIPE;        /* must be at least one full message */        if ( length < sizeof( struct canmsg_t )) {                DEBUGMSG("Trying to write less bytes than a CAN message,");                DEBUGMSG("this will always return 0 !");                return 0;        }        /* Max 8 messages at the time is allowed */        if (length > 8 * sizeof( struct canmsg_t )) {                CANMSG("Trying to write more than is supported.");                return -1;        }        /* must be aliged to message size */        if ( length % sizeof( struct canmsg_t )) {                CANMSG("The number of bytes requested to be written is not a multiple of");                CANMSG("'sizeof(struct canmsg_t)', currently this is not allowed.");                return -1;        }        bytes_to_copy = length;        if ( NULL == ( pmsgobj = filp->private_data )) {                CANMSG("Device is not correctly configured.");                return -1;        }        if (!(pmsgobj->hostchip->flags & CHANNEL_CONFIGURED)) {                CANMSG("Device is not correctly configured, please reopen.");                return -1;        }        /*         * If the output buffer is full, return immediately in case O_NONBLOCK         * has been specified or loop until space becomes available.         */        /* Buffer full */        while ( txspacefree( pmsgobj ) <= sizeof( struct canmsg_t )) {                /* The fifo is Tx full */                if ( filp->f_flags & O_NONBLOCK ) {                        pmsgobj->hostchip->stat.cntTxFifoOvr++;                        return -EAGAIN;                }                if ( wait_event_interruptible( pmsgobj->fifo->writeq,                                               ( txspacefree( pmsgobj ) >                                                 sizeof( struct canmsg_t ))))                        return -ERESTARTSYS;        }        /*         * There's space available in the kernel output buffer.         * Find out wich is smaller: 'length', the number of bytes requested to         * be written or 'spacefree', the number of bytes available in the kernel         * buffer. We copy the least of the two to kernel space.         */        bytes_to_copy = min( bytes_to_copy, txspacefree( pmsgobj ) );        spin_lock_irqsave( &pmsgobj->hostchip->spwlock, irqflags );        if ( pmsgobj->fifo->txwp >= pmsgobj->fifo->txrp )                /* up to end-of-buffer */                bytes_to_copy = min( bytes_to_copy,                                     (u16)( pmsgobj->fifo->ptxbuf +                                            pmsgobj->fifo->txsize -                                            pmsgobj->fifo->txwp ) );        else {                /* the write pointer has wrapped, fill up to rp-1 */                bytes_to_copy = min( bytes_to_copy,                                     (u16)( pmsgobj->fifo->txrp -                                            pmsgobj->fifo->txwp - 1 ) );        }        if ( copy_from_user( pmsgobj->fifo->txwp, buffer, bytes_to_copy )) {                spin_unlock_irqrestore( &pmsgobj->hostchip->spwlock, irqflags );                return -EFAULT;        }        pmsgobj->fifo->txwp += bytes_to_copy;        written = bytes_to_copy;        if ( pmsgobj->fifo->txwp >= ( pmsgobj->fifo->ptxbuf + pmsgobj->fifo->txsize )) {                pmsgobj->fifo->txwp = pmsgobj->fifo->ptxbuf; /* wrapped */        }        /* Initiate transmission in case we are not already transmitting */        if ( ! (pmsgobj->fifo->flags & TX_IN_PROGRESS) ) {                pmsgobj->fifo->flags |= TX_IN_PROGRESS;                DEBUGMSG("try to call pmsgobj->hostchip->send_msg(...)");                pmsgobj->rv = 0;                /* Send the message */                if ( pmsgobj->hostchip->send_msg( pmsgobj,                                                  (struct canmsg_t *)pmsgobj->fifo->txrp ) < 0 ) {                        spin_unlock_irqrestore( &pmsgobj->hostchip->spwlock, irqflags );                        CANMSG("Error sending message");                        return -EIO;                } else {                        /* Message sent */                        pmsgobj->hostchip->stat.cntTxPkt++;                        pmsgobj->hostchip->stat.cntTxData +=                        ((struct canmsg_t *)pmsgobj->fifo->txrp)->length;                        /* Increase buffer pointer */                        pmsgobj->fifo->txrp += sizeof( struct canmsg_t );                        if ( pmsgobj->fifo->txrp >= ( pmsgobj->fifo->ptxbuf +                                                      pmsgobj->fifo->txsize )) {                                pmsgobj->fifo->txrp = pmsgobj->fifo->ptxbuf; /* wrapped */                        }                        DEBUGMSG( "Message sent %lx %lx", (long)pmsgobj->fifo->txrp,                                  (long)pmsgobj->fifo->txwp );                }        }        spin_unlock_irqrestore( &pmsgobj->hostchip->spwlock, irqflags );        return written;}////////////////////////////////////////////////////////////////////////////////* * txspacefree * * Calculates the free fifo space. */static inline u16 txspacefree( struct msgobj_t *pmsgobj ){        u16 rv;        unsigned long irqflags;        spin_lock_irqsave( &pmsgobj->hostchip->spwlock, irqflags );        if ( pmsgobj->fifo->txrp == pmsgobj->fifo->txwp )                rv = pmsgobj->fifo->txsize;        else                rv = ( ( pmsgobj->fifo->txrp + pmsgobj->fifo->txsize -                         pmsgobj->fifo->txwp ) % pmsgobj->fifo->txsize );        spin_unlock_irqrestore( &pmsgobj->hostchip->spwlock, irqflags );        return rv;}

⌨️ 快捷键说明

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