]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/write.c
CAN driver infrastructure redesign to LinCAN-0.2 version
[lincan.git] / lincan / src / write.c
index 98ad046294db3e6970ef4e9e62f52d6e5ced2da3..287400304fad118eb7a660af34689de62c081df0 100644 (file)
@@ -1,18 +1,13 @@
 /* write.c
  * Linux CAN-bus device driver.
  * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
  * This software is released under the GPL-License.
- * Version 0.7  6 Aug 2001
+ * Version lincan-0.2  9 Jul 2003
  */
 
 #include <linux/autoconf.h>
-#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
-#define MODVERSIONS
-#endif
-
-#if defined (MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 
 #define __NO_VERSION__
 #include <linux/module.h>
 
 ssize_t can_write(struct file *file, const char *buffer, size_t length, loff_t *offset)
 {
+       struct canuser_t *canuser = (struct canuser_t*)(file->private_data);
        struct msgobj_t *obj;
-       struct chip_t *chip;
-       struct canmsg_t *write_msg;
-       struct canfifo_t *fifo;
+       struct canmsg_t msg_buff;
+       struct canque_ends_t *qends;
+       struct canque_edge_t *qedge;
+       struct canque_slot_t *slot;
        int ret = 0;
-       int space = 0;
-       int written = 0;
        int bytes_to_copy = 0;
-       long can_timeout = 1;
+
+       if(!canuser || (canuser->magic != CAN_USER_MAGIC)){
+               CANMSG("can_close: bad canuser magic\n");
+               return -ENODEV;
+       }
 
        if (length < sizeof(struct canmsg_t)) {
                DEBUGMSG("Trying to write less bytes than a CAN message,\n");
@@ -52,124 +51,59 @@ ssize_t can_write(struct file *file, const char *buffer, size_t length, loff_t *
        } 
 
        /* Initialize hardware pointers */
-       if ( (obj = objects_p[MINOR_NR]) == NULL) {
+       obj = canuser->msgobj;
+       if (obj == NULL) {
                CANMSG("Could not assign buffer structure\n");
                return -1;
        }
-       if ( (chip = obj->hostchip) == NULL) {
-               CANMSG("Device is not correctly configured,\n");
-               CANMSG("please reload the driver\n");
-               return -1;
-       }
-       if ( (fifo = obj->fifo) == NULL) {
-               CANMSG("Could not assign buffer memory\n");
-               return -1;
-       }
+       qends = canuser->qends;
 
-       /* Initialize pointer to the first message to be sent */
-       write_msg = fifo->tx_writep;
 
-       /* Calculate free buffer space */
-       cli();
-       space = ((int)fifo->tx_writep < (int)fifo->tx_readp) ? 
-                       ((int)fifo->tx_readp - (int)fifo->tx_writep) : 
-                       ((int)fifo->tx_readp - (int)fifo->tx_writep + 
-                                                       (int)fifo->tx_size);
-       sti();
+       /* Prepare first message */
+       copy_from_user(&msg_buff, buffer, sizeof(struct canmsg_t));
 
        /* If the output buffer is full, return immediately in case O_NONBLOCK
         * has been specified or loop until space becomes available.
         */
-       while (space < sizeof(struct canmsg_t)) {
+       if ((ret=canque_get_inslot4id(qends, &qedge, &slot, 
+                       0, msg_buff.id, 0))<0){
                DEBUGMSG("Buffer is full\n");
                if (file->f_flags & O_NONBLOCK)
                        return -EAGAIN;
-               can_timeout = interruptible_sleep_on_timeout(&fifo->writeq, 
-                                                               CANTIMEOUT);
-               if (signal_pending(current))
-                       return -EINTR;
-               if (!can_timeout)
+               if(ret < -1)
+                       return -EIO;
+
+               ret=canque_get_inslot4id_wait_kern(qends, &qedge, &slot, 
+                                               0, msg_buff.id, 0);
+               if(ret<0) {
+                       if (signal_pending(current))
+                               return -EINTR;
+                       /*if (!can_timeout)*/
                        return -EIO;
-               cli();
-               space = ((int)fifo->tx_writep < (int)fifo->tx_readp) ? 
-                       ((int)fifo->tx_readp - (int)fifo->tx_writep) : 
-                       ((int)fifo->tx_readp - (int)fifo->tx_writep + 
-                                                       (int)fifo->tx_size);
-               sti();
+               }
        }
+       slot->msg=msg_buff;
+       canque_put_inslot(qends, qedge, slot);
+       buffer += sizeof(struct canmsg_t);
+       bytes_to_copy = length-sizeof(struct canmsg_t);
 
-       /* There's space available in the kernel output buffer.
-        * Find out wich is smaller: 'length', the number of bytes requested to
-        * be written or 'space', the number of bytes available in the kernel 
-        * buffer. We copy the least of the two to kernel space.
+       /* 
+        * Try to send more messages
         */
-//     space = space - (space % sizeof(struct canmsg_t)); // round it
-       bytes_to_copy = space < length ? space : length;
-       copy_from_user(fifo->tx_writep, buffer, bytes_to_copy);
-       written = bytes_to_copy;
        while (bytes_to_copy > 0) {
-               fifo->tx_writep++;
-               if (fifo->tx_writep >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
-                       fifo->tx_writep = fifo->buf_tx_entry;
+               /* Prepare first message */
+               copy_from_user(&msg_buff, buffer, sizeof(struct canmsg_t));
+               /* Get slot */
+               if(canque_get_inslot4id(qends, &qedge, &slot, 
+                       0, msg_buff.id, 0) < 0) break;
+               slot->msg=msg_buff;
+               canque_put_inslot(qends, qedge, slot);
+               buffer += sizeof(struct canmsg_t);
                bytes_to_copy -= sizeof(struct canmsg_t);
        }
 
-       /* Copy the data to be transmitted into the output buffer */
-/*     while ( (written < length) && (space >= sizeof(struct canmsg_t)) ) {
-               copy_from_user(fifo->tx_writep,buffer, sizeof(struct canmsg_t));
-               cli();
-               fifo->tx_writep++;
-               if (fifo->tx_writep >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
-                       fifo->tx_writep = fifo->buf_tx_entry;
-               buffer += sizeof(struct canmsg_t);
-               written += sizeof(struct canmsg_t);
-               space = ((int)fifo->tx_writep < (int)fifo->tx_readp) ?
-                       ((int)fifo->tx_readp - (int)fifo->tx_writep) :
-                       ((int)fifo->tx_readp - (int)fifo->tx_writep + 
-                                                       (int)fifo->tx_size);
-               sti();
-       } */
-
-       /* Initiate transmission in case we are not already transmitting */
-       cli();
-       if (!fifo->tx_in_progress) {
-               fifo->tx_in_progress = 1;
-               sti();
-               if ( (ret = chip->chipspecops->pre_write_config(chip, obj, 
-                                                       write_msg)) < 0) {
-                       CANMSG("Error initializing hardware for sending\n");
-                       return -EIO;
-               }
-               obj->ret = 0;
-               if ( (ret = chip->chipspecops->send_msg(chip, obj, 
-                                                       write_msg)) < 0) {
-                       CANMSG("Error sending message\n");
-                       return -EIO;
-               }
-               /* If O_SYNC is specified wait for successfull transmission */
-/*             while (1) {
-                       cli();
-                       if ( (!file->f_flags & O_SYNC) || 
-                                               (!fifo->tx_in_progress)) {
-                               sti();
-                               if (obj->ret < 0)
-                                       return obj->ret;
-                               else
-                                       return written;
-                       }
-                       cli();
-                       if (fifo->tx_in_progress) {
-                               can_timeout = interruptible_sleep_on_timeout(
-                                               &fifo->writeq, CANTIMEOUT);
-                       }
-                       sti();
-                       if (signal_pending(current))
-                               return -EINTR;
-                       if (!can_timeout)
-                               return -EIO;
-               } */
+        if(file->f_flags & O_SYNC) {
+               canque_sync_wait_kern(qends, qedge);
        }
-       sti();
-
-       return written;
+       return length-bytes_to_copy;
 }