📄 write.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 + -