From a682f9de48bcce43fba6141fbdb4d451914e0bb4 Mon Sep 17 00:00:00 2001 From: ppisa Date: Thu, 25 Nov 2004 21:45:00 +0000 Subject: [PATCH] Separated normal read and RTR assisted read transfer. I have that long time on in my mind. RTR based transfer in in its own IOCTL, where it belongs. This simplified normal read and made ABI more POSIX compliant. RTR code should be rewritten to be really functional. We are starting new development period now. --- lincan/include/can.h | 1 + lincan/include/ioctl.h | 2 + lincan/src/Makefile.omk | 3 +- lincan/src/Makefile.std | 2 +- lincan/src/ioctl.c | 10 +++ lincan/src/ioctl_remote.c | 93 +++++++++++++++++++++++++++ lincan/src/read.c | 131 ++++++-------------------------------- lincan/src/write.c | 1 + 8 files changed, 128 insertions(+), 115 deletions(-) create mode 100644 lincan/src/ioctl_remote.c diff --git a/lincan/include/can.h b/lincan/include/can.h index 8a93684..b3b265c 100644 --- a/lincan/include/can.h +++ b/lincan/include/can.h @@ -77,6 +77,7 @@ struct can_baudparams_t { #define CANQUE_FILTER _IOW(CAN_IOC_MAGIC, 10, struct canfilt_t) #define CANQUE_FLUSH _IO(CAN_IOC_MAGIC, 11) #define CONF_BAUDPARAMS _IOW(CAN_IOC_MAGIC, 11, struct can_baudparams_t) +#define CANRTR_READ _IOWR(CAN_IOC_MAGIC, 12, struct canmsg_t) #ifdef __cplusplus } /* extern "C"*/ diff --git a/lincan/include/ioctl.h b/lincan/include/ioctl.h index e1e3acf..e780c28 100644 --- a/lincan/include/ioctl.h +++ b/lincan/include/ioctl.h @@ -9,3 +9,5 @@ int can_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); int can_ioctl_query(struct canuser_t *canuser, unsigned long what); +int can_ioctl_remote_read(struct canuser_t *canuser, struct canmsg_t *rtr_msg, + unsigned long rtr_id, int options); diff --git a/lincan/src/Makefile.omk b/lincan/src/Makefile.omk index 863cfdc..fe1bfa9 100644 --- a/lincan/src/Makefile.omk +++ b/lincan/src/Makefile.omk @@ -43,6 +43,7 @@ lincan_SOURCES = can_queue.c can_quekern.c main.c modparms.c \ devcommon.c setup.c finish.c irq.c boardlist.c \ sja1000p.c sja1000.c i82527.c \ open.c close.c read.c write.c ioctl.c select.c fasync.c \ - proc.c ioctl_query.c $(lincan_cards_SOURCES) $(lincan_rtl_SOURCES) + proc.c ioctl_query.c ioctl_remote.c \ + $(lincan_cards_SOURCES) $(lincan_rtl_SOURCES) endif #CONFIG_OC_LINCAN diff --git a/lincan/src/Makefile.std b/lincan/src/Makefile.std index 7d04da3..c70ce4c 100644 --- a/lincan/src/Makefile.std +++ b/lincan/src/Makefile.std @@ -142,7 +142,7 @@ O_OBJS += can_queue.o can_quekern.o devcommon.o main.o modparms.o \ setup.o finish.o irq.o boardlist.o \ sja1000p.o sja1000.o i82527.o \ open.o proc.o close.o write.o read.o \ - ioctl.o ioctl_query.o select.o fasync.o + ioctl.o ioctl_query.o ioctl_remote.o select.o fasync.o # Objects with exported symbols (-DEXPORT_SYMTAB) OX_OBJS = # Module objects diff --git a/lincan/src/ioctl.c b/lincan/src/ioctl.c index 6edca99..63aaea1 100644 --- a/lincan/src/ioctl.c +++ b/lincan/src/ioctl.c @@ -84,6 +84,16 @@ int can_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned } break; } + + case CANRTR_READ: { + int ret; + struct canmsg_t rtr_msg; + + copy_from_user(&rtr_msg, (void*)arg, sizeof(struct canmsg_t)); + ret = can_ioctl_remote_read(canuser, &rtr_msg, rtr_msg.id, 0); + if(ret<0) return ret; + copy_to_user((void*)arg, &rtr_msg, sizeof(struct canmsg_t)); + } case CONF_BAUD: { channel = arg & 0xff; diff --git a/lincan/src/ioctl_remote.c b/lincan/src/ioctl_remote.c new file mode 100644 index 0000000..68f3670 --- /dev/null +++ b/lincan/src/ioctl_remote.c @@ -0,0 +1,93 @@ +/* ioctl_remote.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 lincan-0.3 17 Nov 2004 + */ + +#include "../include/can.h" +#include "../include/can_sysdep.h" +#include "../include/main.h" +#include "../include/read.h" +#include "../include/ioctl.h" + +/* This is the 'RTR' read handler for remote transmission request messages */ +int can_ioctl_remote_read(struct canuser_t *canuser, struct canmsg_t *rtr_msg, + unsigned long rtr_id, int options) +{ + can_spin_irqflags_t flags; + struct rtr_id *rtr_current, *new_rtr_entry; + struct msgobj_t *obj; + struct canchip_t *chip; + /*struct canque_ends_t *qends;*/ + + DEBUGMSG("Remote transmission request\n"); + + /*qends = canuser->qends;*/ + + /* Initialize hardware pointers */ + obj = canuser->msgobj; + if (obj == NULL) { + CANMSG("Could not assign buffer structure\n"); + return -ENODEV; + } + + if ( (chip = obj->hostchip) == NULL) { + CANMSG("Device is not correctly configured,\n"); + CANMSG("please reload the driver.\n"); + return -ENODEV; + } + + can_spin_lock_irqsave(&hardware_p->rtr_lock, flags); + if (hardware_p->rtr_queue == NULL) { //No remote messages pending + new_rtr_entry=(struct rtr_id *)kmalloc(sizeof(struct rtr_id),GFP_ATOMIC); + if (new_rtr_entry == NULL) { + can_spin_unlock_irqrestore(&hardware_p->rtr_lock, + flags); + return -ENOMEM; + } + hardware_p->rtr_queue=new_rtr_entry; + } + else { + rtr_current=hardware_p->rtr_queue; + while (rtr_current->next != NULL) + rtr_current=rtr_current->next; + new_rtr_entry=(struct rtr_id *)kmalloc(sizeof(struct rtr_id),GFP_ATOMIC); + rtr_current->next=new_rtr_entry; + } + init_waitqueue_head(&new_rtr_entry->rtr_wq); + new_rtr_entry->id = rtr_id; + new_rtr_entry->rtr_message = rtr_msg; + new_rtr_entry->next=NULL; + + can_spin_unlock_irqrestore(&hardware_p->rtr_lock, flags); + + /* Send remote transmission request */ + chip->chipspecops->remote_request(chip,obj); + obj->ret = 0; + interruptible_sleep_on(&new_rtr_entry->rtr_wq); + + can_spin_lock_irqsave(&hardware_p->rtr_lock, flags); + if (hardware_p->rtr_queue == new_rtr_entry) { + if (new_rtr_entry->next != NULL) + hardware_p->rtr_queue=new_rtr_entry->next; + else + hardware_p->rtr_queue=NULL; + } + else { + rtr_current=hardware_p->rtr_queue; + while (rtr_current->next != new_rtr_entry) + rtr_current=rtr_current->next; + if (new_rtr_entry->next != NULL) + rtr_current->next=new_rtr_entry->next; + else + rtr_current->next=NULL; + } + can_spin_unlock_irqrestore(&hardware_p->rtr_lock, flags); + kfree(new_rtr_entry); + + return obj->ret; +} + diff --git a/lincan/src/read.c b/lincan/src/read.c index 384bf1b..c16c76b 100644 --- a/lincan/src/read.c +++ b/lincan/src/read.c @@ -11,17 +11,30 @@ #include "../include/can_sysdep.h" #include "../include/main.h" #include "../include/read.h" -#include "../include/ioctl.h" /* This is the 'Normal' read handler for normal transmission messages */ -inline ssize_t can_std_read(struct file *file, struct canque_ends_t *qends, - struct msgobj_t *obj, char *buffer, size_t length) +ssize_t can_read(struct file *file, char *buffer, size_t length, loff_t *offset) { - int ret; + struct canuser_t *canuser = (struct canuser_t*)(file->private_data); + struct canque_ends_t *qends; int bytes_to_copy; struct canque_edge_t *qedge; struct canque_slot_t *slot; - + int ret; + + if(!canuser || (canuser->magic != CAN_USER_MAGIC)){ + CANMSG("can_read: bad canuser magic\n"); + return -ENODEV; + } + + if (length < sizeof(struct canmsg_t)) { + DEBUGMSG("Trying to read less bytes than a CAN message, \n"); + DEBUGMSG("this will always return zero.\n"); + return 0; + } + + qends = canuser->qends; + ret=canque_test_outslot(qends, &qedge, &slot); if(ret<0){ if (file->f_flags & O_NONBLOCK) { @@ -59,111 +72,3 @@ inline ssize_t can_std_read(struct file *file, struct canque_ends_t *qends, return length-bytes_to_copy; } -/* This is the 'RTR' read handler for remote transmission request messages */ -inline ssize_t can_rtr_read(struct canchip_t *chip, struct msgobj_t *obj, - char *buffer) -{ - can_spin_irqflags_t flags; - struct rtr_id *rtr_current, *new_rtr_entry; - struct canmsg_t read_msg; - - DEBUGMSG("Remote transmission request\n"); - - copy_from_user(&read_msg, buffer, sizeof(struct canmsg_t)); - - can_spin_lock_irqsave(&hardware_p->rtr_lock, flags); - if (hardware_p->rtr_queue == NULL) { //No remote messages pending - new_rtr_entry=(struct rtr_id *)kmalloc(sizeof(struct rtr_id),GFP_ATOMIC); - if (new_rtr_entry == NULL) { - can_spin_unlock_irqrestore(&hardware_p->rtr_lock, - flags); - return -ENOMEM; - } - hardware_p->rtr_queue=new_rtr_entry; - } - else { - rtr_current=hardware_p->rtr_queue; - while (rtr_current->next != NULL) - rtr_current=rtr_current->next; - new_rtr_entry=(struct rtr_id *)kmalloc(sizeof(struct rtr_id),GFP_ATOMIC); - rtr_current->next=new_rtr_entry; - } - init_waitqueue_head(&new_rtr_entry->rtr_wq); - new_rtr_entry->id = read_msg.id; - new_rtr_entry->rtr_message = &read_msg; - new_rtr_entry->next=NULL; - - can_spin_unlock_irqrestore(&hardware_p->rtr_lock, flags); - - /* Send remote transmission request */ - chip->chipspecops->remote_request(chip,obj); - obj->ret = 0; - interruptible_sleep_on(&new_rtr_entry->rtr_wq); - - can_spin_lock_irqsave(&hardware_p->rtr_lock, flags); - if (hardware_p->rtr_queue == new_rtr_entry) { - if (new_rtr_entry->next != NULL) - hardware_p->rtr_queue=new_rtr_entry->next; - else - hardware_p->rtr_queue=NULL; - } - else { - rtr_current=hardware_p->rtr_queue; - while (rtr_current->next != new_rtr_entry) - rtr_current=rtr_current->next; - if (new_rtr_entry->next != NULL) - rtr_current->next=new_rtr_entry->next; - else - rtr_current->next=NULL; - } - can_spin_unlock_irqrestore(&hardware_p->rtr_lock, flags); - kfree(new_rtr_entry); - - copy_to_user(buffer, &read_msg, sizeof(struct canmsg_t)); - - return obj->ret; -} - -ssize_t can_read(struct file *file, char *buffer, size_t length, loff_t *offset) -{ - struct canuser_t *canuser = (struct canuser_t*)(file->private_data); - struct msgobj_t *obj; - struct canchip_t *chip; - struct canmsg_t read_msg; - struct canque_ends_t *qends; - int ret=0; - - if(!canuser || (canuser->magic != CAN_USER_MAGIC)){ - CANMSG("can_read: bad canuser magic\n"); - return -ENODEV; - } - - if (length < sizeof(struct canmsg_t)) { - DEBUGMSG("Trying to read less bytes than a CAN message, \n"); - DEBUGMSG("this will always return zero.\n"); - return 0; - } - /* Initialize hardware pointers */ - obj = canuser->msgobj; - if (obj == NULL) { - CANMSG("Could not assign buffer structure\n"); - return -1; - } - qends = canuser->qends; - if ( (chip = obj->hostchip) == NULL) { - CANMSG("Device is not correctly configured,\n"); - CANMSG("please reload the driver.\n"); - return -1; - } - - copy_from_user(&read_msg, buffer, sizeof(struct canmsg_t)); - if (read_msg.flags & MSG_RTR) - /* FIXME: RTR processing should go to its own IOCTLs */ - ret = can_rtr_read(chip, obj, buffer); - else - ret = can_std_read(file, qends, obj, buffer, length); - - return ret; -} - - diff --git a/lincan/src/write.c b/lincan/src/write.c index 6ef80ee..dccade1 100644 --- a/lincan/src/write.c +++ b/lincan/src/write.c @@ -10,6 +10,7 @@ #include "../include/can.h" #include "../include/can_sysdep.h" #include "../include/main.h" +#include "../include/write.h" ssize_t can_write(struct file *file, const char *buffer, size_t length, loff_t *offset) { -- 2.39.2