X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/97078fff5202521b758c9081d75580880417a123..11132ea490f9e860744ee4f851c67e7fb4444231:/lincan/src/write.c diff --git a/lincan/src/write.c b/lincan/src/write.c index 98ad046..2874003 100644 --- a/lincan/src/write.c +++ b/lincan/src/write.c @@ -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 -#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS) -#define MODVERSIONS -#endif - -#if defined (MODVERSIONS) -#include -#endif #define __NO_VERSION__ #include @@ -26,15 +21,19 @@ 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; }