CAN driver infrastructure redesign to LinCAN-0.2 version
authorppisa <ppisa>
Mon, 25 Aug 2003 03:52:35 +0000 (03:52 +0000)
committerppisa <ppisa>
Mon, 25 Aug 2003 03:52:35 +0000 (03:52 +0000)
62 files changed:
lincan/README
lincan/TODO
lincan/include/aim104.h
lincan/include/can.h
lincan/include/can_queue.h [new file with mode: 0644]
lincan/include/cc_can104.h
lincan/include/close.h
lincan/include/constants.h
lincan/include/devcommon.h [new file with mode: 0644]
lincan/include/i82527.h
lincan/include/ioctl.h
lincan/include/irq.h
lincan/include/m437.h
lincan/include/main.h
lincan/include/modparms.h
lincan/include/nsi.h
lincan/include/open.h
lincan/include/pc-i03.h
lincan/include/pccan.h
lincan/include/pcccan.h
lincan/include/pcm3680.h
lincan/include/pikronisa.h
lincan/include/pip.h
lincan/include/proc.h
lincan/include/read.h
lincan/include/select.h
lincan/include/setup.h
lincan/include/sja1000.h
lincan/include/smartcan.h
lincan/include/ssv.h
lincan/include/template.h
lincan/src/Makefile
lincan/src/aim104.c
lincan/src/bfadcan.c
lincan/src/can_queue.c [new file with mode: 0644]
lincan/src/cc_can104.c
lincan/src/close.c
lincan/src/devcommon.c [new file with mode: 0644]
lincan/src/i82527.c
lincan/src/ioctl.c
lincan/src/irq.c
lincan/src/m437.c
lincan/src/main.c
lincan/src/modparms.c
lincan/src/nsi.c
lincan/src/open.c
lincan/src/pc_i03.c
lincan/src/pccan.c
lincan/src/pcccan.c
lincan/src/pcm3680.c
lincan/src/pikronisa.c
lincan/src/pip.c
lincan/src/proc.c
lincan/src/read.c
lincan/src/select.c
lincan/src/setup.c
lincan/src/sja1000.c
lincan/src/sja1000p.c
lincan/src/smartcan.c
lincan/src/ssv.c
lincan/src/template.c
lincan/src/write.c

index f2095a8..b7a546b 100644 (file)
-Because we are not able to contact original author Arnaud Westenberg,
-and we have put piece of work to bugfixes and enhancements of the
-driver, we decided to offer our latest version to more tests.
-Please, if you know Arnaud's new address, contact us.
-Most of new bugs belongs to 
+               Linux CAN Driver (LinCAN) version 0.2 snapshot
+               Pavel Pisa <pisa@cmp.felk.cvut.cz>
+                       OCERA team member
+                       <http://www.ocera.org>
 
-    Pavel Pisa pisa@cmp.felk.cvut.cz 
-and Tomasz Motylewski, T.Motylewski@bfad.de
 
-Main enhancements:
-  interrupts service cleanup and partial redesign
-  deep module build redesign
-  support for select
-  preliminary support for 2.5.48 (UP only now)
-  CAN Ethernet proxy
+INTRODUCTION
+============
+The LinCAN is an implementation of the Linux CAN-bus device driver supporting
+more CAN controller chips and many CAN interface boards. Its development
+has long history already. The OCERA version of the driver has new better
+designed internal structure, adds new features (as support for open by multiple
+applications, select system call) and other enhancements.
+  
+The driver consist of four main layers:
+  - chip level manipulation routines
+  - board specific support
+  - message queues
+  - user-space API and ABI character device interface
 
-------------------------------------------------------------------------
 
-README for the linux CAN-bus driver.
-Written by Arnaud Westenberg email:arnaud@wanadoo.nl
-This software is released under the GPL-License.
-Version 0.7  6 Aug 2001
+DRIVER HISTORY
+==============
 
-Modified version can-0.7.1-pi2.2
+The driver originates in The Linux Lab Project
+  http://www.llp.fu-berlin.de/
+then it has been first rewritten by Arnaud Westenberg
+  http://home.wanadoo.nl/arnaud/
+now it is developed and maintained as part of OCERA framework
+  http://www.ocera.org/
 
-This version adds new Makefile system.
-DEVFS support
-Select/poll support for read/write events
-Preliminary cleanups for 2.5.xx kernels,
-it cannot work with SMP 2.5.xx until we get rid off
-CLI ans STI global directives
+I am unable to contact previous maintainer Arnaud Westenberg
+(arnaud@wanadoo.nl). If you know something about him, I like
+to hear it.
+
+Versions:
+
+can-0.7.1      latest driver version version published
+               by Arnaud Westenberg
+
+can-0.7.1-tm5  the enhanced version with better support of
+               SJA1000 PeliCAN mode and CAN Ethernet proxy
+               contributed by Tomasz Motylewski <T.Motylewski@bfad.de>
+
+can-0.7.1-pi1  the import and usage of previous version for
+(Dec 2002)     OCERA group purposes
+               
+can-0.7.1-pi3.4 enhanced version with select support and rewritten
+(Mar 2003)     make system for Linux kernels (2.2.x,2.4.x,2.5.x),
+               interrupts service cleanup and partial redesign
+               and DEVFS support
+
+lincan-0.2-pre heavily rewritten infrastructure of the driver based
+(Aug 2003)     on atomic slot management of queues
+
+The actual version of driver have been latest tested it with
+PC104 Advantech PCM3680 dual channel board on 2.4 kernel.
+It takes more time to test it with more cards and polish
+support for 2.2 and 2.6 kernels, but these should be mainly
+cosmetic changes (I hope ;-), infrastructure and original
+support for more than 14 boards with more variants is in.
+
+
+SOURCES AND URLs
+================
+
+The LinCAN driver component page at OCERA web site
+(not updated to the new version yet)
+
+  http://www.ocera.org/download/components/WP7/lincan-0.1.html
+  
+List of related communication components
+  
+  http://www.ocera.org/download/components/WP7/index.html
+
+The CVS repository of OCERA project at SourceForge
+
+  EXTCVS=":pserver:anonymous@cvs.ocera.sourceforge.net:/cvsroot/ocera"
+  cvs -d$EXTCVS login
+  cvs -z3 -d$EXTCVS co ocera
+  
+Web access into CVS
+
+  http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/ocera/ocera/components/comm/can/lincan/
+
+Experimental directory at maintainer (Pavel Pisa's) pages 
+
+  http://cmp.felk.cvut.cz/~pisa/can/
+  http://cmp.felk.cvut.cz/~pisa/can/lincan-YYMMDD.tar.gz
+  
+Please send comments, bug-fixes and enhancements directly to
+me (Pavel Pisa <pisa@cmp.felk.cvut.cz>) or to OCERA discussion
+forum <https://sourceforge.net/forum/forum.php?forum_id=170893> 
+and lists <ocera-development@lists.sourceforge.net>
 
-Changes made by Pavel Pisa pisa@cmp.felk.cvut.cz as preliminary
-study for OCERA Real Time CAN/CANOpen project ORTCAN
 
 COMPILATION
-Just type 'make' at the command line and it should compile without errors.
+===========
+
+Just type 'make' at the command line and driver module should compile
+without errors for current running kernel.
 
-INSTALLATION.
-Currently there's no installation procedure, just compile and load the driver.
+More information can be found in driver documentation at
+  http://cmp.felk.cvut.cz/~pisa/can/
+  http://cmp.felk.cvut.cz/~pisa/can/lincan-X.Y.pdf
+
+INSTALLATION
+============
+Type 'make install'. The driver should be copied into actual kernel version
+modules directory "/lib/modules/x.y.z/kernel/drivers/char".
 
 LOADING
+=======
+
 To load the driver type:
 # insmod can.o hw='your hardware' irq='irq number' io='io address' <options>
 Example: # insmod can.o hw=pip5 irq=4 io=0x8000
@@ -63,7 +135,7 @@ The hw argument can be one of:
 
 options can be one of:
 - major=<nr>, major specifies the major number of the driver.
-- minor=<nr>, you can specify wich minor numbers the driver should use for your
+- minor=<nr>, you can specify which minor numbers the driver should use for your
   hardware.
 - extended=[1|0], configures the driver to use extended message format.
 - pelican=[1|0], configures the driver to set the CAN chips into pelican mode.
index 7a4c555..d2a99aa 100644 (file)
@@ -10,5 +10,5 @@ Version 0.7  6 Aug 2001
 - Proc directory
 - Lot of ioctl's
 
-- Get rid of CLI and STI, they are not longer supported
++ Get rid of CLI and STI, they are not longer supported
   in 2.5.xx kernels
index 5e9c0b8..c269114 100644 (file)
@@ -1,17 +1,19 @@
 /* aim104.h
  * Header file for the Linux CAN-bus 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
  */
 
-int aim104_request_io(unsigned long io_addr);
-int aim104_release_io(unsigned long io_addr);
-int aim104_reset(int card); 
-int aim104_init_hw_data(int card);
-int aim104_init_chip_data(int card, int chipnr);
-int aim104_init_obj_data(int chipnr, int objnr);
+int aim104_request_io(struct candevice_t *candev);
+int aim104_release_io(struct candevice_t *candev);
+int aim104_reset(struct candevice_t *candev); 
+int aim104_init_hw_data(struct candevice_t *candev);
+int aim104_init_chip_data(struct candevice_t *candev, int chipnr);
+int aim104_init_obj_data(struct chip_t *chip, int objnr);
 void aim104_write_register(unsigned char data, unsigned long address);
 unsigned aim104_read_register(unsigned long address);
-int aim104_program_irq(int card);
+int aim104_program_irq(struct candevice_t *candev);
 
index 6ccb6dc..e310732 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef _CANMSG_T_H
+#define _CANMSG_T_H
+
 #include <linux/types.h>
 #include <linux/ioctl.h>
 
@@ -16,6 +19,13 @@ struct canmsg_t {
        unsigned char   data[CAN_MSG_LENGTH];
 } PACKED;
 
+struct canfilt_t {
+       int             flags;
+       int             cob;
+       unsigned long   id;
+       unsigned long   mask;
+};
+
 /* Definitions to use for canmsg_t flags */
 #define MSG_RTR (1<<0)
 #define MSG_OVR (1<<1)
@@ -38,8 +48,11 @@ typedef unsigned short channel_t;
 //#define CONF_TIMING
 //#define CONF_OMODE
 #define CONF_FILTER _IOW(CAN_IOC_MAGIC, 8, unsigned char)
+
 //#define CONF_FENABLE
 //#define CONF_FDISABLE
 
-
 #define STAT _IO(CAN_IOC_MAGIC, 9)
+#define CONF_FILTER_QUE0 _IOW(CAN_IOC_MAGIC, 10, struct canfilt_t)
+
+#endif /*_CANMSG_T_H*/
diff --git a/lincan/include/can_queue.h b/lincan/include/can_queue.h
new file mode 100644 (file)
index 0000000..bf092cd
--- /dev/null
@@ -0,0 +1,453 @@
+#ifndef _CAN_QUEUE_H
+#define _CAN_QUEUE_H
+
+#include <linux/version.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include "./can.h"
+#include "./constants.h"
+
+/* Next is not sctrictly correct, because of 2.3.0, 2.3.1, 2.3.2
+   kernels need next definitions  too */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19)) /* may need correction */
+  #define wait_queue_head_t struct wait_queue *
+  #define wait_queue_t      struct wait_queue
+  #define init_waitqueue_head(queue_head) (*queue_head=NULL)
+  #define init_waitqueue_entry(qentry,qtask) \
+                        (qentry->next=NULL,qentry->task=qtask)
+  #define DECLARE_WAIT_QUEUE_HEAD(name) \
+        struct wait_queue * name=NULL
+  #define DECLARE_WAITQUEUE(wait, current) \
+        struct wait_queue wait = { current, NULL }
+  #define init_MUTEX(sem) (*sem=MUTEX)
+  #define DECLARE_MUTEX(name) struct semaphore name=MUTEX
+#endif /* 2.2.19 */
+
+
+/**
+ * struct canque_slot_t - one CAN message slot in the CAN FIFO queue 
+ * @next: pointer to the next/younger slot
+ * @mrs_do_inp: space for flags and optional command describing action
+ *     associated with slot data
+ * @msg: space for one CAN message
+ *
+ * This structure is used to store CAN messages in the CAN FIFO queue.
+ */
+ struct canque_slot_t {
+       struct canque_slot_t *next;
+       unsigned long slot_flags;
+       struct canmsg_t msg;
+};
+
+#define CAN_SLOTF_CMD  0x00ff  /*  */
+
+/**
+ * struct canque_fifo_t - CAN FIFO queue representation
+ * @fifo_flags: this field holds global flags describing state of the FIFO.
+ *     %CAN_FIFOF_ERROR is set when some error condition occurs.
+ *     %CAN_FIFOF_ERR2BLOCK defines, that error should lead to the FIFO block state.
+ *     %CAN_FIFOF_BLOCK state blocks insertion of the next messages. 
+ *     %CAN_FIFOF_OVERRUN attempt to acquire new slot, when FIFO is full. 
+ *     %CAN_FIFOF_FULL indicates FIFO full state. 
+ *     %CAN_FIFOF_EMPTY indicates no allocated slot in the FIFO.
+ *     %CAN_FIFOF_DEAD condition indication. Used when FIFO is beeing destroyed.
+ * @error_code: futher description of error condition
+ * @head: pointer to the FIFO head, oldest slot
+ * @tail: pointer to the location, where pointer to newly inserted slot
+ *     should be added
+ * @tail: pointer to the location, where pointer to newly inserted slot
+ * @entry: pointer to the memory allocated for the list slots.
+ * @fifo_lock: the lock to ensure atomicity of slot manipulation operations.
+ *
+ * This structure represents CAN FIFO queue. It is implemented as 
+ * a single linked list of slots prepared for processing. The empty slots
+ * are stored in single linked list (@flist).
+ */
+struct canque_fifo_t {
+       unsigned long fifo_flags;
+       unsigned long error_code;
+       struct canque_slot_t *head;     /* points to the oldest entry */
+       struct canque_slot_t **tail;    /* points to NULL pointer for chaining */
+       struct canque_slot_t *flist;    /* points the first entry in the free list */
+       struct canque_slot_t *entry;    /* points to first allocated entry */
+       spinlock_t fifo_lock;   /* spin_lock_irqsave / spin_lock_irqrestore */
+};
+
+#define CAN_FIFOF_DESTROY_b    15
+#define CAN_FIFOF_ERROR_b      14
+#define CAN_FIFOF_ERR2BLOCK_b  13
+#define CAN_FIFOF_BLOCK_b      12
+#define CAN_FIFOF_OVERRUN_b    11
+#define CAN_FIFOF_FULL_b       10
+#define CAN_FIFOF_EMPTY_b      9
+#define CAN_FIFOF_DEAD_b       8
+
+#define CAN_FIFOF_DESTROY      (1<<CAN_FIFOF_DESTROY_b)
+#define CAN_FIFOF_ERROR                (1<<CAN_FIFOF_ERROR_b)
+#define CAN_FIFOF_ERR2BLOCK    (1<<CAN_FIFOF_ERR2BLOCK_b)
+#define CAN_FIFOF_BLOCK                (1<<CAN_FIFOF_BLOCK_b)
+#define CAN_FIFOF_OVERRUN      (1<<CAN_FIFOF_OVERRUN_b)
+#define CAN_FIFOF_FULL         (1<<CAN_FIFOF_FULL_b)
+#define CAN_FIFOF_EMPTY                (1<<CAN_FIFOF_EMPTY_b)
+#define CAN_FIFOF_DEAD         (1<<CAN_FIFOF_DEAD_b)
+
+#define canque_fifo_test_fl(fifo,fifo_fl) \
+  test_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
+#define canque_fifo_set_fl(fifo,fifo_fl) \
+  set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
+#define canque_fifo_clear_fl(fifo,fifo_fl) \
+  clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
+#define canque_fifo_test_and_set_fl(fifo,fifo_fl) \
+  test_and_set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
+#define canque_fifo_test_and_clear_fl(fifo,fifo_fl) \
+  test_and_clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
+
+
+/**
+ * canque_fifo_get_inslot - allocate slot for the input of one CAN message 
+ * @fifo: pointer to the FIFO structure
+ * @slotp: pointer to location to store pointer to the allocated slot.
+ * @cmd: optional command associated with allocated slot.
+ *
+ * Return Value: The function returns negative value if there is no
+ *     free slot in the FIFO queue.
+ */
+static inline
+int canque_fifo_get_inslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp, int cmd)
+{
+       unsigned long flags;
+       struct canque_slot_t *slot;
+       spin_lock_irqsave(&fifo->fifo_lock, flags);
+       /* get the first free slot slot from flist */
+       if(!(slot=fifo->flist)) {
+               canque_fifo_set_fl(fifo,OVERRUN);
+               canque_fifo_set_fl(fifo,FULL);
+               spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+               *slotp=NULL;
+               return -1;
+       }
+       /* adjust free slot list */
+       if(!(fifo->flist=slot->next))
+               canque_fifo_set_fl(fifo,FULL);
+       spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       *slotp=slot;
+       slot->slot_flags=cmd&CAN_SLOTF_CMD;
+       return 1;
+}
+
+/**
+ * canque_fifo_put_inslot - releases slot to further processing
+ * @fifo: pointer to the FIFO structure
+ * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
+ *
+ * Return Value: The nonzero return value indicates, that the queue was empty
+ *     before call to the function. The caller should wake-up output side of the queue.
+ */
+static inline
+int canque_fifo_put_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
+{
+       int ret;
+       unsigned long flags;
+       slot->next=NULL;
+       spin_lock_irqsave(&fifo->fifo_lock, flags);
+       if(*fifo->tail) printk(KERN_CRIT "canque_fifo_put_inslot: fifo->tail != NULL\n");
+       *fifo->tail=slot;
+       fifo->tail=&slot->next;
+       if(canque_fifo_test_and_clear_fl(fifo,EMPTY))
+         ret=CAN_FIFOF_EMPTY;  /* Fifo has been empty before put */
+       else 
+         ret=0;
+       spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       return ret;
+}
+
+/**
+ * canque_fifo_abort_inslot - release and abort slot
+ * @fifo: pointer to the FIFO structure
+ * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
+ *
+ * Return Value: The nonzero value indicates, that fifo was full
+ */
+static inline
+int canque_fifo_abort_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
+{
+       int ret=0;
+       unsigned long flags;
+       spin_lock_irqsave(&fifo->fifo_lock, flags);
+       slot->next=fifo->flist;
+       fifo->flist=slot;
+       if(canque_fifo_test_and_clear_fl(fifo,FULL))
+               ret=CAN_FIFOF_FULL;
+       spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       return ret;
+}
+
+/**
+ * canque_fifo_test_outslot - test and get ready slot from the FIFO
+ * @fifo: pointer to the FIFO structure
+ * @slotp: pointer to location to store pointer to the oldest slot from the FIFO.
+ *
+ * Return Value: The negative value indicates, that queue is empty.
+ *     The positive or zero value represents command stored into slot by
+ *     the call to the function canque_fifo_get_inslot().
+ *     The successfully acquired FIFO output slot has to be released by
+ *     the call canque_fifo_free_outslot() or canque_fifo_again_outslot().
+ */
+static inline
+int canque_fifo_test_outslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp)
+{
+       unsigned long flags;
+       int cmd;
+       struct canque_slot_t *slot;
+       spin_lock_irqsave(&fifo->fifo_lock, flags);
+       if(!(slot=fifo->head)){;
+               canque_fifo_set_fl(fifo,EMPTY);
+               spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+               *slotp=NULL;
+               return -1;
+       }
+       if(!(fifo->head=slot->next))
+               fifo->tail=&fifo->head;
+       spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+
+       *slotp=slot;
+       cmd=slot->slot_flags;
+       return cmd&CAN_SLOTF_CMD;
+}
+
+
+/**
+ * canque_fifo_free_outslot - free processed FIFO slot
+ * @fifo: pointer to the FIFO structure
+ * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
+ *
+ * Return Value: The returned value informs about FIFO state change.
+ *     The mask %CAN_FIFOF_FULL indicates, that the FIFO was full before
+ *     the function call. The mask %CAN_FIFOF_EMPTY informs, that last ready slot
+ *     has been processed.
+ */
+static inline
+int canque_fifo_free_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
+{
+       int ret=0;
+       unsigned long flags;
+       spin_lock_irqsave(&fifo->fifo_lock, flags);
+       slot->next=fifo->flist;
+       fifo->flist=slot;
+       if(canque_fifo_test_and_clear_fl(fifo,FULL))
+               ret=CAN_FIFOF_FULL;
+       if(!(fifo->head)){
+               canque_fifo_set_fl(fifo,EMPTY);
+               ret|=CAN_FIFOF_EMPTY;
+       }
+       spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       return ret;
+}
+
+/**
+ * canque_fifo_again_outslot - interrupt and postpone processing of the slot
+ * @fifo: pointer to the FIFO structure
+ * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
+ *
+ * Return Value: The function cannot fail..
+ */
+static inline
+int canque_fifo_again_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&fifo->fifo_lock, flags);
+       if(!(slot->next=fifo->head))
+               fifo->tail=&slot->next;
+       fifo->head=slot;
+       spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       return 1;
+}
+
+int canque_fifo_flush_slots(struct canque_fifo_t *fifo);
+
+int canque_fifo_init_slots(struct canque_fifo_t *fifo, int slotsnr);
+
+int canque_fifo_done(struct canque_fifo_t *fifo);
+
+#define CANQUEUE_PRIO_NR  3
+
+/* Forward declarations for external types */
+struct msgobj_t;
+struct chip_t;
+
+/**
+ * canque_edge_t - CAN message delivery subsystem graph edge
+ * @fifo: place where primitive @struct canque_fifo_t FIFO is located.
+ * @filtid: the possible CAN message identifiers filter.
+ * @filtmask: the filter mask, the comparison considers only
+ *     @filtid bits corresponding to set bits in the @filtmask field.
+ * @inpeers: the lists of all peer FIFOs connected by their
+ *     input side (@inends) to the same terminal (@struct canque_ends_t).
+ * @outpeers: the lists of all peer FIFOs connected by their
+ *     output side (@outends) to the same terminal (@struct canque_ends_t).
+ * @inends: the pointer to the FIFO input side terminal (@struct canque_ends_t).
+ * @outends: the pointer to the FIFO output side terminal (@struct canque_ends_t).
+ * @edge_used: the atomic usage counter, mainly used for safe destruction of the edge.
+ * @edge_prio: the assigned queue priority from the range 0 to %CANQUEUE_PRIO_NR-1
+ * @edge_num: edge sequential number intended for debugging purposes only
+ */
+struct canque_edge_t {
+       struct canque_fifo_t fifo;
+       unsigned long filtid;
+       unsigned long filtmask;
+       struct list_head inpeers;
+       struct list_head outpeers;
+       struct canque_ends_t *inends;
+       struct canque_ends_t *outends;
+       atomic_t edge_used;
+       int edge_prio;
+       int edge_num;
+};
+
+/**
+ * canque_edge_t - CAN message delivery subsystem graph vertex (FIFO ends)
+ * @active: the array of the lists of active edges directed to the ends structure
+ *     with ready messages. The array is indexed by the edges priorities. 
+ * @idle: the list of the edges directed to the ends structure with empty FIFOs.
+ * @inlist: the list of outgoing edges input sides.
+ * @ends_lock: the lock synchronizing operations between threads accessing
+ *     same ends structure.
+ * @notify: pointer to notify procedure. The next state changes are notified.
+ *     %CANQUEUE_NOTIFY_EMPTY (out->in call) - all slots are processed by FIFO out side. 
+ *     %CANQUEUE_NOTIFY_SPACE (out->in call) - full state negated => there is space for new message.
+ *     %CANQUEUE_NOTIFY_PROC  (in->out call) - empty state negated => out side is requested to process slots.
+ *     %CANQUEUE_NOTIFY_NOUSR (both) - notify, that the last user has released the edge usage
+ *             called with some lock to prevent edge disappear.
+ * @context: space to store ends user specific information
+ * @endinfo: space to store some other ends usage specific informations
+ *     mainly for waking-up by the notify calls.
+ */
+struct canque_ends_t {
+       struct list_head active[CANQUEUE_PRIO_NR];
+       struct list_head idle;
+       struct list_head inlist;
+       spinlock_t ends_lock;   /* spin_lock_irqsave / spin_lock_irqrestore */
+       void (*notify)(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what);
+       void *context;
+       union {
+               struct {
+                       wait_queue_head_t readq;
+                       wait_queue_head_t writeq;
+                       wait_queue_head_t emptyq;
+               } fileinfo;
+               struct {
+                       wait_queue_head_t daemonq;
+                       struct msgobj_t *msgobj;
+                       struct chip_t *chip;
+               } chipinfo;
+       } endinfo;
+};
+
+#define CANQUEUE_NOTIFY_EMPTY 1        /* out -> in - all slots are processed by FIFO out side */
+#define CANQUEUE_NOTIFY_SPACE 2        /* out -> in - full state negated => there is space for new message */
+#define CANQUEUE_NOTIFY_PROC  3        /* in -> out - empty state negated => out side is requested to process slots */
+#define CANQUEUE_NOTIFY_NOUSR 4        /* called with some lock to prevent edge disappear */
+#define CANQUEUE_NOTIFY_DEAD  5        /*  */
+#define CANQUEUE_NOTIFY_ATACH 6        /*  */
+#define CANQUEUE_NOTIFY_FILTCH 7 /* filter changed */
+#define CANQUEUE_NOTIFY_ERROR      0x10000 /* error notifiers */
+#define CANQUEUE_NOTIFY_ERRTX_PREP 0x11001 /* tx preparation error */
+#define CANQUEUE_NOTIFY_ERRTX_SEND 0x11002 /* tx send error */
+#define CANQUEUE_NOTIFY_ERRTX_BUS  0x11003 /* tx bus error */
+
+static inline
+void canque_notify_inends(struct canque_edge_t *qedge, int what)
+{
+       if(qedge->inends)
+               if(qedge->inends->notify)
+                       qedge->inends->notify(qedge->inends,qedge,what);
+}
+
+static inline
+void canque_notify_outends(struct canque_edge_t *qedge, int what)
+{
+       if(qedge->outends)
+               if(qedge->outends->notify)
+                       qedge->outends->notify(qedge->outends,qedge,what);
+}
+
+static inline
+void canque_notify_bothends(struct canque_edge_t *qedge, int what)
+{
+       canque_notify_inends(qedge, what);
+       canque_notify_outends(qedge, what);
+}
+
+static inline
+void canque_activate_edge(struct canque_ends_t *inends, struct canque_edge_t *qedge)
+{
+       unsigned long flags;
+       struct canque_ends_t *outends;
+       if(qedge->edge_prio>=CANQUEUE_PRIO_NR)
+               qedge->edge_prio=CANQUEUE_PRIO_NR-1;
+       spin_lock_irqsave(&inends->ends_lock, flags);
+       if((outends=qedge->outends)){
+               spin_lock(&outends->ends_lock);
+               spin_lock(&qedge->fifo.fifo_lock);
+               if(!canque_fifo_test_fl(&qedge->fifo,EMPTY)){
+                       list_del(&qedge->outpeers);
+                       list_add_tail(&qedge->outpeers,&outends->active[qedge->edge_prio]);
+               }
+               spin_unlock(&qedge->fifo.fifo_lock);
+               spin_unlock(&outends->ends_lock);
+
+       }
+       spin_unlock_irqrestore(&inends->ends_lock, flags);
+}
+
+int canque_get_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd);
+       
+int canque_get_inslot4id(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
+       int cmd, unsigned long id, int prio);
+       
+int canque_put_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot);
+
+int canque_abort_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot);
+
+int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg);
+
+int canque_test_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
+
+int canque_free_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot);
+
+int canque_again_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot);
+
+int canque_set_filt(struct canque_edge_t *qedge,
+       unsigned long filtid, unsigned long filtmask);
+
+int canque_flush(struct canque_edge_t *qedge);
+
+struct canque_edge_t *canque_new_edge_kern(int slotsnr);
+
+int canque_get_inslot4id_wait_kern(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
+       int cmd, unsigned long id, int prio);
+
+int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
+
+int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge);
+
+int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends);
+
+int canqueue_ends_init_gen(struct canque_ends_t *qends);
+
+int canqueue_ends_init_kern(struct canque_ends_t *qends);
+
+int canqueue_ends_done_kern(struct canque_ends_t *qends, int sync);
+
+#endif /*_CAN_QUEUE_H*/
index 64da797..c557f5c 100644 (file)
@@ -1,17 +1,19 @@
 /* cc_can104.h
  * Header file for the Linux CAN-bus 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
  */
 
-int cc104_request_io(unsigned long io_addr);
-int cc104_release_io(unsigned long io_addr);
-int cc104_reset(int card); 
-int cc104_init_hw_data(int card);
-int cc104_init_chip_data(int card, int chipnr);
-int cc104_init_obj_data(int chipnr, int objnr);
+int cc104_request_io(struct candevice_t *candev);
+int cc104_release_io(struct candevice_t *candev);
+int cc104_reset(struct candevice_t *candev); 
+int cc104_init_hw_data(struct candevice_t *candev);
+int cc104_init_chip_data(struct candevice_t *candev, int chipnr);
+int cc104_init_obj_data(struct chip_t *chip, int objnr);
 void cc104_write_register(unsigned char data, unsigned long address);
 unsigned cc104_read_register(unsigned long address);
-int cc104_program_irq(int card);
+int cc104_program_irq(struct candevice_t *candev);
 
index f164b31..7c8cdee 100644 (file)
@@ -1,8 +1,10 @@
 /* close.h
  * Header file for the Linux CAN-bus 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
  */
 
 int can_close(struct inode *inode, struct file *file);
index 10af2ce..2d86cc3 100644 (file)
@@ -1,8 +1,10 @@
 /* constants.h
  * Header file for the Linux CAN-bus 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
  */
 
 #ifdef __CONSTANTS_H__
 #define SIE (1<<2)
 #define EIE (1<<3)
 
-#define SPACING 0x3c0
-
 /* These flags can be used for the msgobj_t structure flags data entry */
-#define OPENED (1<<0)
-#define BUFFERS_ALLOCATED (1<<1)
+#define OBJ_OPENED (1<<0)
+#define OBJ_BUFFERS_ALLOCATED (1<<1)
+#define OBJ_TX_REQUEST (1<<2)
+#define OBJ_TX_LOCK (1<<3)
 
 /* These flags can be used for the chip_t structure flags data entry */
-#define CONFIGURED (1<<0)
-#define SEGMENTED (1<<1)
+#define CHIP_CONFIGURED (1<<0)
+#define CHIP_SEGMENTED (1<<1)
 
 /* These flags can be used for the candevices_t structure flags data entry */
 #define PROGRAMMABLE_IRQ (1<<0)
diff --git a/lincan/include/devcommon.h b/lincan/include/devcommon.h
new file mode 100644 (file)
index 0000000..e19471e
--- /dev/null
@@ -0,0 +1,19 @@
+/* devcommon.h - common device code
+ * Linux CAN-bus device driver.
+ * 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.2  9 Jul 2003
+ */
+
+#include <linux/fs.h>
+#include <linux/version.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "./can.h"
+#include "./constants.h"
+#include "./can_queue.h"
+
+int canqueue_ends_init_chip(struct canque_ends_t *qends, struct chip_t *chip, struct msgobj_t *obj);
index 14df44e..c80ed00 100644 (file)
@@ -1,8 +1,10 @@
 /* i82527.h
  * Header file for the Linux CAN-bus 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
  */
 
 int i82527_enable_configuration(struct chip_t *chip);
@@ -29,6 +31,9 @@ int i82527_set_btregs(struct chip_t *chip, unsigned short btr0,
 int i82527_start_chip(struct chip_t *chip);
 int i82527_stop_chip(struct chip_t *chip);
 int i82527_check_tx_stat(struct chip_t *chip);
+irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+
+#define MSG_OFFSET(object) ((object)*0x10)
 
 #define iCTL 0x00              // Control Register
 #define iSTAT 0x01             // Status Register
@@ -165,3 +170,6 @@ enum i82527_iMSGCFG {
        MCFG_XTD = 1<<2,                // Extended Identifier
        MCFG_DIR = 1<<3                 // Direction is Transmit
 };
+
+void i82527_seg_write_reg(const struct chip_t *chip, unsigned char data, unsigned address);
+unsigned i82527_seg_read_reg(const struct chip_t *chip, unsigned address);
index 794b779..c45e104 100644 (file)
@@ -1,8 +1,10 @@
 /* ioctl.h
  * Header file for the Linux CAN-bus 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
  */
 
 int can_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
index 7410882..959a94b 100644 (file)
@@ -1,10 +1,12 @@
 /* irq.h
  * Header file for the Linux CAN-bus 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
  */
 
-void i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
-void sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
-void dummy_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t dummy_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
index 869dc1e..2c77bd3 100644 (file)
@@ -1,19 +1,21 @@
 /* m437.h
  * Header file for the Linux CAN-bus 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
  *
  * Header file for the SECO M437 (see m437.c for details)
  */
 
-int m437_request_io(unsigned long io_addr);
-int m437_release_io(unsigned long io_addr);
-int m437_reset(int card); 
-int m437_init_hw_data(int card);
-int m437_init_chip_data(int card, int chipnr);
-int m437_init_obj_data(int chipnr, int objnr);
+int m437_request_io(struct candevice_t *candev);
+int m437_release_io(struct candevice_t *candev);
+int m437_reset(struct candevice_t *candev); 
+int m437_init_hw_data(struct candevice_t *candev);
+int m437_init_chip_data(struct candevice_t *candev, int chipnr);
+int m437_init_obj_data(struct chip_t *chip, int objnr);
 void m437_write_register(unsigned char data, unsigned long address);
 unsigned m437_read_register(unsigned long address);
-int m437_program_irq(int card);
+int m437_program_irq(struct candevice_t *candev);
 int m437_register(struct hwspecops_t *hwspecops);
index c811d87..81f1818 100644 (file)
@@ -1,16 +1,20 @@
 /* main.h
  * Header file for the Linux CAN-bus 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 <asm/io.h>
 #include <linux/fs.h>
 #include <linux/version.h>
 #include <linux/wait.h>
-#include <asm/io.h>
+#include <linux/interrupt.h>
 #include "./can.h"
 #include "./constants.h"
+#include "./can_queue.h"
 
 #ifdef CAN_DEBUG
        #define DEBUGMSG(fmt,args...) printk(KERN_ERR "can.o (debug): " fmt,\
        (minor(file->f_dentry->d_inode->i_rdev))
 #endif /* Linux kernel > 2.5.7 */
 
-#define MSG_OFFSET(object) ((object)*0x10)
+#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) && !defined(IRQ_RETVAL))
+   typedef void irqreturn_t;
+   #define IRQ_NONE
+   #define IRQ_HANDLED
+   #define IRQ_RETVAL(x)
+#endif /* <=2.5.67 */
 
 struct canhardware_t {
        int nr_boards;
@@ -42,14 +51,17 @@ struct canhardware_t {
 };
 
 struct candevice_t {
-       char *hwname;
-       unsigned long io_addr;
-       unsigned long res_addr;
+       char *hwname;                   /* text board type */
+       int candev_idx;                 /* board index in canhardware_t.candevice[] */
+       unsigned long io_addr;          /* IO/physical MEM address */
+       unsigned long res_addr;         /* optional seset register port */
+       unsigned long dev_base_addr;    /* CPU translated IO/virtual MEM address */
        unsigned int flags;
 
        /* Hardware chip configuration. In case of multiple chips *chip
         * is the first in an array of chip_t structures.
         */
+       int nr_all_chips;
        int nr_82527_chips;
        int nr_sja1000_chips;
        struct chip_t *chip[MAX_HW_CHIPS];
@@ -61,11 +73,20 @@ struct candevice_t {
 
 struct chip_t {
        char *chip_type;
+       int chip_idx;   /* chip index in candevice_t.chip[] */
        int chip_irq;
        unsigned long chip_base_addr;
        unsigned int flags;
        int clock; // Chip clock in Hz
 
+       /* This is copy of the chip->hostdevice->hwspecops->read_register
+        * and the chip->hostdevice->hwspecops->write_register.
+        * The pointers were added for performance reasons, and are initialized
+        * by init_chip_struct() from values given by hardware specific init_hwspecops().
+        */
+       void (*write_register)(unsigned char data,unsigned long address);
+       unsigned (*read_register)(unsigned long address);
+
        /* sja_cdr_reg holds hardware specific options for the Clock Divider
         * register. Options defined in the sja1000.h file:
         * CDR_CLKOUT_MASK, CDR_CLK_OFF, CDR_RXINPEN, CDR_CBP, CDR_PELICAN
@@ -98,30 +119,49 @@ struct chip_t {
        struct chipspecops_t *chipspecops;
 
        struct candevice_t *hostdevice;
+       
+       int max_objects;        /* 1 for sja1000, 15 for */
 };
 
 struct msgobj_t {
        unsigned long obj_base_addr;
-       unsigned int minor;
-       unsigned int object;
-       unsigned int flags; 
+       unsigned int minor;     /* associated device minor number  */
+       unsigned int object;    /* object number in chip_t +1 for debug printk */
+       unsigned long flags; 
        int ret;
 
-       struct canfifo_t *fifo;
+       struct canque_ends_t *qends;
+       struct canque_edge_t *tx_qedge;
+       struct canque_slot_t *tx_slot;
+       struct canmsg_t rx_msg;
 
        struct chip_t *hostchip;
+
+       atomic_t obj_used;
+       struct list_head obj_users;
+};
+
+#define CAN_USER_MAGIC 0x05402033
+
+struct canuser_t {
+       struct list_head peers;
+       struct canque_ends_t *qends;
+        struct file *file;      /* back ptr to file */
+       struct msgobj_t *msgobj;
+       struct canque_edge_t *rx_edge0; /* simplifies IOCTL */
+       int magic;
 };
 
 struct hwspecops_t {
-       int (*request_io)(unsigned long io_addr);
-       int (*release_io)(unsigned long io_addr);
-       int (*reset)(int card);
-       int (*init_hw_data)(int card);
-       int (*init_chip_data)(int card, int chipnr);
-       int (*init_obj_data)(int chipnr, int objnr);
+       int (*request_io)(struct candevice_t *candev);
+       int (*release_io)(struct candevice_t *candev);
+       int (*reset)(struct candevice_t *candev);
+       int (*init_hw_data)(struct candevice_t *candev);
+       int (*init_chip_data)(struct candevice_t *candev, int chipnr);
+       int (*init_obj_data)(struct chip_t *chip, int objnr);
+       int (*program_irq)(struct candevice_t *candev);
        void (*write_register)(unsigned char data,unsigned long address);
        unsigned (*read_register)(unsigned long address);
-       int (*program_irq)(int card);
 };
 
 struct chipspecops_t {
@@ -143,13 +183,14 @@ struct chipspecops_t {
                                                        struct canmsg_t *msg);
        int (*remote_request)(struct chip_t *chip, struct msgobj_t *obj);
        int (*check_tx_stat)(struct chip_t *chip);
+       int (*wakeup_tx)(struct chip_t *chip, struct msgobj_t *obj);
        int (*enable_configuration)(struct chip_t *chip);
        int (*disable_configuration)(struct chip_t *chip);
        int (*set_btregs)(struct chip_t *chip, unsigned short btr0, 
                                                        unsigned short btr1);
        int (*start_chip)(struct chip_t *chip);
        int (*stop_chip)(struct chip_t *chip);
-       void (*irq_handler)(int irq, void *dev_id, struct pt_regs *regs);
+       irqreturn_t (*irq_handler)(int irq, void *dev_id, struct pt_regs *regs);
 };
 
 struct mem_addr {
@@ -157,45 +198,6 @@ struct mem_addr {
        struct mem_addr *next;
 };
 
-/* Structure for the drivers main input and output buffers. The readq, writeq
- * entries are the wait queues for the driver to sleep on in case of blocking
- * read/write calls. buf_rx_entry and buf_tx_entry are pointers to the input and
- * output buffers. The buffers are dynamically allocated. The tx_readp,
- * tx_writep, rx_readp and rx_writep pointers are the various read/write 
- * pointers used when reading or writing the input and output buffers. The 
- * rx/tx_size entries are the dynamically allocated input and output buffer size
- * The rx/tx_in_progress entries are used to determine whether the device is 
- * already set up for transmission.
- */
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
-struct canfifo_t {
-       struct wait_queue *readq, *writeq; 
-       struct canmsg_t *buf_tx_entry;
-       struct canmsg_t *buf_rx_entry; 
-       struct canmsg_t *tx_readp;
-       struct canmsg_t *rx_writep;
-       struct canmsg_t *tx_writep;
-       struct canmsg_t *rx_readp;
-       int rx_size, tx_size;
-       volatile int rx_in_progress, tx_in_progress;
-       /*int head, tail;*/ /* removed */
-};
-#else
-struct canfifo_t {
-       struct __wait_queue_head readq;
-       struct __wait_queue_head writeq;
-       struct canmsg_t *buf_tx_entry;
-       struct canmsg_t *buf_rx_entry; 
-       struct canmsg_t *tx_readp;
-       struct canmsg_t *rx_writep;
-       struct canmsg_t *tx_writep;
-       struct canmsg_t *rx_readp;
-       int rx_size, tx_size;
-       volatile int rx_in_progress, tx_in_progress;
-       /*int head, tail;*/ /* removed */
-};
-#endif
-
 /* Structure for the RTR queue */
 struct rtr_id {
        unsigned long id;
@@ -217,7 +219,6 @@ extern int irq[MAX_IRQ];
 extern unsigned long io[MAX_HW_CARDS];
 
 extern struct canhardware_t *hardware_p;
-extern struct candevice_t *candevices_p[MAX_HW_CARDS];
 extern struct chip_t *chips_p[MAX_TOT_CHIPS];
 extern struct msgobj_t *objects_p[MAX_TOT_MSGOBJS];
 
@@ -226,31 +227,37 @@ extern struct mem_addr *mem_head;
 /* Inline function to write to the hardware registers. The argument address is 
  * relative to the memory map of the chip and not the absolute memory address.
  */
-extern inline void can_write_reg(const struct chip_t *chip, unsigned char data, unsigned short address)
+extern inline void can_write_reg(const struct chip_t *chip, unsigned char data, unsigned address)
 {
-       unsigned short segment_number;
        unsigned long address_to_write;
-
        address_to_write = chip->chip_base_addr+address;
+       chip->write_register(data, address_to_write);
+}
 
-       if ( (chip->flags & SEGMENTED) != 0) {
-               segment_number = (unsigned short)(address >> 6);
-               address_to_write += SPACING * segment_number;
-       }
+extern inline unsigned can_read_reg(const struct chip_t *chip, unsigned address)
+{
+       unsigned long address_to_read;
+       address_to_read = chip->chip_base_addr+address;
+       return chip->read_register(address_to_read);
+}
 
-       chip->hostdevice->hwspecops->write_register(data, address_to_write);
+extern inline void canobj_write_reg(const struct chip_t *chip, const struct msgobj_t *obj,
+                               unsigned char data, unsigned address)
+{
+       unsigned long address_to_write;
+       address_to_write = obj->obj_base_addr+address;
+       chip->write_register(data, address_to_write);
 }
 
-extern inline unsigned can_read_reg(const struct chip_t *chip, unsigned short address)
+extern inline unsigned canobj_read_reg(const struct chip_t *chip, const struct msgobj_t *obj,
+                               unsigned address)
 {
-       unsigned short segment_number;
        unsigned long address_to_read;
+       address_to_read = obj->obj_base_addr+address;
+       return chip->read_register(address_to_read);
+}
 
-       address_to_read = chip->chip_base_addr+address;
+int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base);
+int can_request_io_region(unsigned long start, unsigned long n, const char *name);
+void can_release_io_region(unsigned long start, unsigned long n);
 
-       if ( (chip->flags & SEGMENTED) != 0) {
-               segment_number = (unsigned short)(address >> 6);
-               address_to_read += SPACING * segment_number;
-       }
-       return chip->hostdevice->hwspecops->read_register(address_to_read);
-}
index 18879fc..4fa44f6 100644 (file)
@@ -1,8 +1,10 @@
 /* mod_parms.h
  * Header file for the Linux CAN-bus 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
  */
 
 int parse_mod_parms(void);
index fd69113..ec6db23 100644 (file)
@@ -1,17 +1,19 @@
 /* nsi.h
  * Header file for the Linux CAN-bus 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
  */
 
-int nsi_request_io(unsigned long io_addr);
-int nsi_release_io(unsigned long io_addr);
-int nsi_reset(int card); 
-int nsi_init_hw_data(int card);
-int nsi_init_chip_data(int card, int chipnr);
-int nsi_init_obj_data(int chipnr, int objnr);
+int nsi_request_io(struct candevice_t *candev);
+int nsi_release_io(struct candevice_t *candev);
+int nsi_reset(struct candevice_t *candev); 
+int nsi_init_hw_data(struct candevice_t *candev);
+int nsi_init_chip_data(struct candevice_t *candev, int chipnr);
+int nsi_init_obj_data(struct chip_t *chip, int objnr);
 void nsi_write_register(unsigned char data, unsigned long address);
 unsigned nsi_read_register(unsigned long address);
-int nsi_program_irq(int card);
+int nsi_program_irq(struct candevice_t *candev);
 
index 997bd9f..fca1bf1 100644 (file)
@@ -1,8 +1,10 @@
 /* open.h
  * Header file for the Linux CAN-bus 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
  */
 
 int can_open(struct inode *inode, struct file *file);
index beb8aed..9b34ca3 100644 (file)
@@ -1,17 +1,19 @@
 /* pc-i03.h
  * Header file for the Linux CAN-bus 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
  */
 
-int pci03_request_io(unsigned long io_addr);
-int pci03_release_io(unsigned long io_addr);
-int pci03_reset(int card); 
-int pci03_init_hw_data(int card);
-int pci03_init_chip_data(int card, int chipnr);
-int pci03_init_obj_data(int chipnr, int objnr);
+int pci03_request_io(struct candevice_t *candev);
+int pci03_release_io(struct candevice_t *candev);
+int pci03_reset(struct candevice_t *candev); 
+int pci03_init_hw_data(struct candevice_t *candev);
+int pci03_init_chip_data(struct candevice_t *candev, int chipnr);
+int pci03_init_obj_data(struct chip_t *chip, int objnr);
 void pci03_write_register(unsigned char data, unsigned long address);
 unsigned pci03_read_register(unsigned long address);
-int pci03_program_irq(int card);
+int pci03_program_irq(struct candevice_t *candev);
 
index f5b8901..d47804c 100644 (file)
@@ -1,24 +1,26 @@
 /* pccan.h
  * Header file for the Linux CAN-bus 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
  */
 
-int pccanf_request_io(unsigned long io_addr);
-int pccanf_release_io(unsigned long io_addr);
-int pccand_request_io(unsigned long io_addr);
-int pccand_release_io(unsigned long io_addr);
-int pccanq_request_io(unsigned long io_addr);
-int pccanq_release_io(unsigned long io_addr);
-int pccanf_reset(int card);
-int pccand_reset(int card);
-int pccanq_reset(int card); 
-int pccan_init_hw_data(int card);
-int pccan_init_chip_data(int card, int chipnr);
-int pccan_init_obj_data(int chipnr, int objnr);
+int pccanf_request_io(struct candevice_t *candev);
+int pccanf_release_io(struct candevice_t *candev);
+int pccand_request_io(struct candevice_t *candev);
+int pccand_release_io(struct candevice_t *candev);
+int pccanq_request_io(struct candevice_t *candev);
+int pccanq_release_io(struct candevice_t *candev);
+int pccanf_reset(struct candevice_t *candev);
+int pccand_reset(struct candevice_t *candev);
+int pccanq_reset(struct candevice_t *candev); 
+int pccan_init_hw_data(struct candevice_t *candev);
+int pccan_init_chip_data(struct candevice_t *candev, int chipnr);
+int pccan_init_obj_data(struct chip_t *chip, int objnr);
 void pccan_write_register(unsigned char data, unsigned long address);
 unsigned pccan_read_register(unsigned long address);
-int pccan_program_irq(int card);
+int pccan_program_irq(struct candevice_t *candev);
 
 
index 77cdd80..cf98553 100644 (file)
@@ -1,17 +1,19 @@
 /* pcccan.h
  * Header file for the Linux CAN-bus 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
  */
 
-int pcccan_request_io(unsigned long io_addr);
-int pcccan_release_io(unsigned long io_addr);
-int pcccan_reset(int card); 
-int pcccan_init_hw_data(int card);
-int pcccan_init_chip_data(int card, int chipnr);
-int pcccan_init_obj_data(int chipnr, int objnr);
+int pcccan_request_io(struct candevice_t *candev);
+int pcccan_release_io(struct candevice_t *candev);
+int pcccan_reset(struct candevice_t *candev); 
+int pcccan_init_hw_data(struct candevice_t *candev);
+int pcccan_init_chip_data(struct candevice_t *candev, int chipnr);
+int pcccan_init_obj_data(struct chip_t *chip, int objnr);
 void pcccan_write_register(unsigned char data, unsigned long address);
 unsigned pcccan_read_register(unsigned long address);
-int pcccan_program_irq(int card);
+int pcccan_program_irq(struct candevice_t *candev);
 
index c0d5957..324854e 100644 (file)
@@ -1,17 +1,19 @@
 /* pcm3680.h
  * Header file for the Linux CAN-bus 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
  */
 
-int pcm3680_request_io(unsigned long io_addr);
-int pcm3680_release_io(unsigned long io_addr);
-int pcm3680_reset(int card); 
-int pcm3680_init_hw_data(int card);
-int pcm3680_init_chip_data(int card, int chipnr);
-int pcm3680_init_obj_data(int chipnr, int objnr);
+int pcm3680_request_io(struct candevice_t *candev);
+int pcm3680_release_io(struct candevice_t *candev);
+int pcm3680_reset(struct candevice_t *candev); 
+int pcm3680_init_hw_data(struct candevice_t *candev);
+int pcm3680_init_chip_data(struct candevice_t *candev, int chipnr);
+int pcm3680_init_obj_data(struct chip_t *chip, int objnr);
 void pcm3680_write_register(unsigned char data, unsigned long address);
 unsigned pcm3680_read_register(unsigned long address);
-int pcm3680_program_irq(int card);
+int pcm3680_program_irq(struct candevice_t *candev);
 
index 7fa56dd..360cc08 100644 (file)
@@ -1,21 +1,22 @@
 /* pikronisa.h
  * Header file for the Linux CAN-bus driver.
  * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Added by Pavel Pisa pisa@cmp.felk.cvut.cz
+ * 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
  *
  * Support for PiKRON Ltd ISA CAN card using 
  * memory mapped SJA1000 controller
- * Added by Pavel Pisa pisa@cmp.felk.cvut.cz
  */
 
-int pikronisa_request_io(unsigned long io_addr);
-int pikronisa_release_io(unsigned long io_addr);
-int pikronisa_reset(int card); 
-int pikronisa_init_hw_data(int card);
-int pikronisa_init_chip_data(int card, int chipnr);
-int pikronisa_init_obj_data(int chipnr, int objnr);
+int pikronisa_request_io(struct candevice_t *candev);
+int pikronisa_release_io(struct candevice_t *candev);
+int pikronisa_reset(struct candevice_t *candev); 
+int pikronisa_init_hw_data(struct candevice_t *candev);
+int pikronisa_init_chip_data(struct candevice_t *candev, int chipnr);
+int pikronisa_init_obj_data(struct chip_t *chip, int objnr);
+int pikronisa_program_irq(struct candevice_t *candev);
 void pikronisa_write_register(unsigned char data, unsigned long address);
 unsigned pikronisa_read_register(unsigned long address);
-int pikronisa_program_irq(int card);
 
index fefe48d..c32b2b5 100644 (file)
@@ -1,17 +1,19 @@
 /* pip.h
  * Header file for the Linux CAN-bus 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
  */
 
-int pip5_request_io(unsigned long io_addr);
-int pip5_release_io(unsigned long io_addr);
-int pip5_reset(int card); 
-int pip5_init_hw_data(int card);
-int pip5_init_chip_data(int card, int chipnr);
-int pip5_init_obj_data(int chipnr, int objnr);
+int pip5_request_io(struct candevice_t *candev);
+int pip5_release_io(struct candevice_t *candev);
+int pip5_reset(struct candevice_t *candev); 
+int pip5_init_hw_data(struct candevice_t *candev);
+int pip5_init_chip_data(struct candevice_t *candev, int chipnr);
+int pip5_init_obj_data(struct chip_t *chip, int objnr);
 void pip5_write_register(unsigned char data, unsigned long address);
 unsigned pip5_read_register(unsigned long address);
-int pip5_program_irq(int card);
+int pip5_program_irq(struct candevice_t *candev);
 
index 8a3d004..c07ab0a 100644 (file)
@@ -1,8 +1,10 @@
 /* proc.h
  * Header file for the Linux CAN-bus 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/proc_fs.h>
index 9716105..09e01d1 100644 (file)
@@ -1,8 +1,10 @@
 /* read.h
  * Header file for the Linux CAN-bus 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
  */
 
 ssize_t can_read(struct file *file,char *buffer,size_t length,loff_t *offset);
index cdf9195..3f24002 100644 (file)
@@ -1,10 +1,10 @@
 /* select.h
  * Header file for the Linux CAN-bus driver.
  * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Added by Pavel Pisa pisa@cmp.felk.cvut.cz
+ * email:pisa@cmp.felk.cvut.cz
  * This software is released under the GPL-License.
- * Version 0.7.1-pi2  15 Nov 2002
- * 
- * added by Pavel Pisa pisa@cmp.felk.cvut.cz
+ * Version lincan-0.2  9 Jul 2003
  */
 
 unsigned int can_poll(struct file *file, poll_table *wait);
index 3e9a35a..551adac 100644 (file)
@@ -1,8 +1,10 @@
 /* setup.h
  * Header file for the Linux CAN-bus 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
  */
 
 int init_hw_struct(void);
index 9c6a6c6..35865b8 100644 (file)
@@ -1,8 +1,10 @@
 /* sja1000.h
  * Header file for the Linux CAN-bus 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
  */
 
 int sja1000_enable_configuration(struct chip_t *chip);
@@ -21,7 +23,7 @@ int sja1000_set_btregs(struct chip_t *chip, unsigned short btr0,
                                                        unsigned short btr1);
 int sja1000_start_chip(struct chip_t *chip);
 int sja1000_stop_chip(struct chip_t *chip);
-void sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs);
 
 /* BasicCAN mode address map */
 #define SJACR          0x00    /* Control register */
index 939df87..74fa2aa 100644 (file)
@@ -1,16 +1,18 @@
 /* smartcan.h
  * Header file for the Linux CAN-bus 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
  */
 
-int smartcan_request_io(unsigned long io_addr);
-int smartcan_release_io(unsigned long io_addr);
-int smartcan_reset(int card);
-int smartcan_init_hw_data(int card);
-int smartcan_init_chip_data(int card, int chipnr);
-int smartcan_init_obj_data(int chipnr,int objnr);
+int smartcan_request_io(struct candevice_t *candev);
+int smartcan_release_io(struct candevice_t *candev);
+int smartcan_reset(struct candevice_t *candev);
+int smartcan_init_hw_data(struct candevice_t *candev);
+int smartcan_init_chip_data(struct candevice_t *candev, int chipnr);
+int smartcan_init_obj_data(struct chip_t *chip, int objnr);
 void smartcan_write_register(unsigned char data, unsigned long address);
 unsigned smartcan_read_register(unsigned long address);
 
index d6a1151..9371487 100644 (file)
@@ -5,13 +5,13 @@
  * Version 0.6  18 Sept 2000
  */
 
-int ssv_request_io(unsigned long io_addr);
-int ssv_release_io(unsigned long io_addr);
-int ssv_reset(int card);
-int ssv_init_hw_data(int card);
-int ssv_init_chip_data(int card, int chipnr);
-int ssv_init_obj_data(int chipnr, int objnr);
+int ssv_request_io(struct candevice_t *candev);
+int ssv_release_io(struct candevice_t *candev);
+int ssv_reset(struct candevice_t *candev);
+int ssv_init_hw_data(struct candevice_t *candev);
+int ssv_init_chip_data(struct candevice_t *candev, int chipnr);
+int ssv_init_obj_data(struct chip_t *chip, int objnr);
 void ssv_write_register(unsigned char data, unsigned long address);
 unsigned ssv_read_register(unsigned long address);
-int ssv_program_irq(int card);
+int ssv_program_irq(struct candevice_t *candev);
 
index 410a46b..f61e31f 100644 (file)
@@ -1,17 +1,19 @@
 /* template.h
  * Header file for the Linux CAN-bus 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
  */
 
-int template_request_io(unsigned long io_addr);
-int template_release_io(unsigned long io_addr);
-int template_reset(int card); 
-int template_init_hw_data(int card);
-int template_init_chip_data(int card, int chipnr);
-int template_init_obj_data(int chipnr, int objnr);
+int template_request_io(struct candevice_t *candev);
+int template_release_io(struct candevice_t *candev);
+int template_reset(struct candevice_t *candev); 
+int template_init_hw_data(struct candevice_t *candev);
+int template_init_chip_data(struct candevice_t *candev, int chipnr);
+int template_init_obj_data(struct chip_t *chip, int objnr);
 void template_write_register(unsigned char data, unsigned long address);
 unsigned template_read_register(unsigned long address);
-int template_program_irq(int card);
+int template_program_irq(struct candevice_t *candev);
 
index b83aa6d..8f5cfa2 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile for the Linux CAN-bus driver.
 # Written by Arnaud Westenberg email:arnaud@wanadoo.nl
 # This software is released under the GPL-License.
-# Version 0.7  6 Aug 2001
+# Version lincan-0.2  9 Aug 2003
 #
 # This version is adapted from uLan Communication driver
 # (C) Copyright 1999 by Pavel Pisa pisa@cmp.felk.cvut.cz
 #KERNEL_LOCATION=/usr/src/linux
 #KERNEL_LOCATION=/usr/src/linux-2.2.19
 #KERNEL_LOCATION=/usr/src/linux-2.2.22
-#KERNEL_LOCATION=/usr/src/linux-2.5.47
-
-# Comment-out next two lines, if you do not build driver 
-# in the OCERA source tree
-TOP=../../../../..
-KERNEL_LOCATION=$(TOP)/kernel/linux
+#KERNEL_LOCATION=/usr/src/linux-2.5.69
+#KERNEL_LOCATION=/home/cvs/ocera/ocera-build/kernel/linux
 
 # Enable debugging messages
 DEBUG = y
@@ -33,6 +29,10 @@ SUPPORTED_CARDS = pip pccan smartcan nsi cc_can104 \
                  pc_i03 pcm3680 aim104 m437 pcccan ssv \
                  bfadcan pikronisa template
 
+#SUPPORTED_CARDS = pcm3680 bfadcan pikronisa template
+
+#SUPPORTED_CARDS = pikronisa
+
 ########## Don't change anything under this line ################
 
 # currently running kernel
@@ -91,7 +91,8 @@ O_TARGET     = can.o
 endif
 # Regular object files
 O_OBJS      += $(SUPPORTED_CARDS:%=%.o)
-O_OBJS       += main.o modparms.o setup.o sja1000.o i82527.o close.o ioctl.o \
+O_OBJS       += can_queue.o devcommon.o main.o modparms.o setup.o \
+               sja1000.o i82527.o close.o ioctl.o \
                open.o write.o read.o sja1000p.o irq.o select.o
 # Objects with exported symbols (-DEXPORT_SYMTAB)
 OX_OBJS      = 
@@ -111,12 +112,18 @@ can-objs := $(O_OBJS)
 obj-y := $(O_OBJS)
 obj-m := can.o
 
+ifndef KERNEL_MODULE_V26
+FINAL_MODULE_OBJS=$(obj-m)
+else
+FINAL_MODULE_OBJS=$(obj-m:%.o=%.ko)
+endif
+
 ########## Source/target independent buil of module #############
 
 all : default
 
 default : make_this_module
-       cp can.o ../can.o
+       cp $(FINAL_MODULE_OBJS) ../$(FINAL_MODULE_OBJS)
 
 dep: make_this_module_dep
 
@@ -133,17 +140,16 @@ make_this_module: .supported_cards.h
        echo Module target $(obj-m)
        echo Module objects $(can-objs)
        DIR=`pwd`; (cd $(KERNEL_LOCATION); make SUBDIRS=$$DIR modules)
-       for f in $(obj-m:%.o=%) ; do if [ -f $$f.ko ] ; then cp -u $$f.ko $$f.o ; fi ; done
 
 make_this_module_dep:
        DIR=`pwd`; (cd $(KERNEL_LOCATION); make SUBDIRS=$$DIR dep)
 
 install_this_module: make_this_module
-       su -c "mkdir -v -p $(MODULE_CHAR_LOC); cp -v $(obj-m) $(MODULE_CHAR_LOC)"
+       su -c "mkdir -v -p $(MODULE_CHAR_LOC) && cp -v $(FINAL_MODULE_OBJS) $(MODULE_CHAR_LOC)"
 
 clean:
        rm -f $(M_OBJS) $(MX_OBJS) $(O_OBJS) $(OX_OBJS) $(obj-m) $(obj-m:%.o=%.ko) \
-                       .*.o.flags .*.o.cmd .depend .supported_cards.h *~
+                       .*.o.flags .*.o.cmd .*.ko.cmd .depend .supported_cards.h *~
 
 ifndef KERNEL_MODULE_V26
 include $(KERNEL_LOCATION)/Rules.make
index d679b52..da8afc0 100644 (file)
@@ -1,18 +1,13 @@
 /* aim104.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
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/template.c
  */
-int aim104_request_io(unsigned long io_addr)
+int aim104_request_io(struct candevice_t *candev)
 {
-       if (check_region(io_addr,IO_RANGE)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr);
+       if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
                return -ENODEV;
-       }
-       else {
-               request_region(io_addr,IO_RANGE,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + IO_RANGE - 1);
+       } else {
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
        }
        return 0;
 }
@@ -69,9 +62,9 @@ int aim104_request_io(unsigned long io_addr)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int aim104_release_io(unsigned long io_addr)
+int aim104_release_io(struct candevice_t *candev)
 {
-       release_region(io_addr,IO_RANGE);
+       can_release_io_region(candev->io_addr,IO_RANGE);
 
        return 0;
 }
@@ -86,17 +79,17 @@ int aim104_release_io(unsigned long io_addr)
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/template.c
  */
-int aim104_reset(int card)
+int aim104_reset(struct candevice_t *candev)
 {
        int i=0;
 
        DEBUGMSG("Resetting aim104 hardware ...\n");
 
-       aim104_write_register(0x00, candevices_p[card]->io_addr + SJACR);
+       aim104_write_register(0x00, candev->io_addr + SJACR);
                                                                        
        /* Check hardware reset status chip 0 */
        i=0;
-       while ( (aim104_read_register(candevices_p[card]->io_addr + SJACR) 
+       while ( (aim104_read_register(candev->io_addr + SJACR) 
                                                        & CR_RR) && (i<=15) ) {
                udelay(20000);
                i++;
@@ -130,12 +123,13 @@ int aim104_reset(int card)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int aim104_init_hw_data(int card
+int aim104_init_hw_data(struct candevice_t *candev
 {
-       candevices_p[card]->res_addr=RESET_ADDR;
-       candevices_p[card]->nr_82527_chips=0;
-       candevices_p[card]->nr_sja1000_chips=1;
-       candevices_p[card]->flags |= ~PROGRAMMABLE_IRQ;
+       candev->res_addr=RESET_ADDR;
+       candev->nr_82527_chips=0;
+        candev->nr_sja1000_chips=1;
+       candev->nr_all_chips=1;
+       candev->flags &= ~PROGRAMMABLE_IRQ;
 
        return 0;
 }
@@ -170,14 +164,14 @@ int aim104_init_hw_data(int card)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int aim104_init_chip_data(int card, int chipnr)
+int aim104_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       candevices_p[card]->chip[chipnr]->chip_type=CHIP_TYPE;
-       candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->clock = 16000000;
-       candevices_p[card]->chip[chipnr]->flags = 0;
-       candevices_p[card]->chip[chipnr]->sja_cdr_reg = 0x08;
-       candevices_p[card]->chip[chipnr]->sja_ocr_reg = 0xfa;
+       candev->chip[chipnr]->chip_type=CHIP_TYPE;
+       candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+       candev->chip[chipnr]->clock = 16000000;
+       candev->chip[chipnr]->flags = 0;
+       candev->chip[chipnr]->sja_cdr_reg = 0x08;
+       candev->chip[chipnr]->sja_ocr_reg = 0xfa;
 
        return 0;
 }
@@ -199,10 +193,10 @@ int aim104_init_chip_data(int card, int chipnr)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int aim104_init_obj_data(int chipnr, int objnr)
+int aim104_init_obj_data(struct chip_t *chip, int objnr)
 {
-       chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr;
-       chips_p[chipnr]->msgobj[objnr]->flags=0;
+       chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
+       chip->msgobj[objnr]->flags=0;
        
        return 0;
 }
@@ -219,7 +213,7 @@ int aim104_init_obj_data(int chipnr, int objnr)
  * Return value: The function returns zero on success or %-ENODEV on failure
  * File: src/template.c
  */
-int aim104_program_irq(int card)
+int aim104_program_irq(struct candevice_t *candev)
 {
        return 0;
 }
index 930e91a..3e145f6 100644 (file)
@@ -1,8 +1,10 @@
 /* bfadcan.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
  */ 
 
 /* This file is intended as a bfadcan file for currently unsupported hardware.
 #define __NO_VERSION__ /* this is not a main module, do not include module info */
 
 #include <linux/autoconf.h>
-#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
-#define MODVERSIONS
-#endif
 
-#if defined (MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
 
 #include <linux/version.h>
@@ -77,15 +73,13 @@ void bfadcan_write_register(unsigned char data, unsigned long address);
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/bfadcan.c
  */
-int bfadcan_request_io(unsigned long io_addr)
+int bfadcan_request_io(struct candevice_t *candev)
 {
-       if (check_region(io_addr,IO_RANGE)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr);
+       if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
                return -ENODEV;
-       }
-       else {
-               request_region(io_addr,IO_RANGE,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + IO_RANGE - 1);
+       } else {
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
        }
        return 0;
 }
@@ -102,9 +96,9 @@ int bfadcan_request_io(unsigned long io_addr)
  * Return Value: The function always returns zero
  * File: src/bfadcan.c
  */
-int bfadcan_release_io(unsigned long io_addr)
+int bfadcan_release_io(struct candevice_t *candev)
 {
-       release_region(io_addr,IO_RANGE);
+       can_release_io_region(candev->io_addr,IO_RANGE);
 
        return 0;
 }
@@ -119,11 +113,11 @@ int bfadcan_release_io(unsigned long io_addr)
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/bfadcan.c
  */
-int bfadcan_reset(int card)
+int bfadcan_reset(struct candevice_t *candev)
 {
 
        int i;
-       struct chip_t *chip=candevices_p[card]->chip[0];
+       struct chip_t *chip=candev->chip[0];
        unsigned cdr;
        
        bfadcan_write_register(MOD_RM, chip->chip_base_addr+SJAMOD);
@@ -168,12 +162,13 @@ int bfadcan_reset(int card)
  * Return Value: The function always returns zero
  * File: src/bfadcan.c
  */
-int bfadcan_init_hw_data(int card
+int bfadcan_init_hw_data(struct candevice_t *candev
 {
-       candevices_p[card]->res_addr=RESET_ADDR;
-       candevices_p[card]->nr_82527_chips=NR_82527;
-       candevices_p[card]->nr_sja1000_chips=NR_SJA1000;
-       candevices_p[card]->flags |= 0 /* PROGRAMMABLE_IRQ */ ;
+       candev->res_addr=RESET_ADDR;
+       candev->nr_82527_chips=NR_82527;
+       candev->nr_sja1000_chips=NR_SJA1000;
+       candev->nr_all_chips=NR_82527+NR_SJA1000;
+       candev->flags |= 0 /* PROGRAMMABLE_IRQ */ ;
 
        return 0;
 }
@@ -211,24 +206,24 @@ int bfadcan_init_hw_data(int card)
  * Return Value: The function always returns zero
  * File: src/bfadcan.c
  */
-int bfadcan_init_chip_data(int card, int chipnr)
+int bfadcan_init_chip_data(struct candevice_t *candev, int chipnr)
 {
        unsigned int id1, id2;
-       candevices_p[card]->chip[chipnr]->chip_type=CHIP_TYPE;
-       candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->clock = clock_freq;
-       candevices_p[card]->chip[chipnr]->int_cpu_reg = iCPU_DSC;
-       candevices_p[card]->chip[chipnr]->int_clk_reg = iCLK_SL1;
-       candevices_p[card]->chip[chipnr]->int_bus_reg = iBUS_CBY;
-       candevices_p[card]->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
-       candevices_p[card]->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL |
+       candev->chip[chipnr]->chip_type=CHIP_TYPE;
+       candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+       candev->chip[chipnr]->clock = clock_freq;
+       candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
+       candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
+       candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
+       candev->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
+       candev->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL |
                                                                OCR_TX0_LH;
        id1 = inb(0xe284);
        id2 = inb(0xe285);
 
 
-       CANMSG("can driver ver 0.7.1-tm5, at %04lx, CPLD v%d.%d.%d.%d\n",
-                                       candevices_p[card]->chip[chipnr]->chip_base_addr,
+       CANMSG("can driver ver lincan-0.2, at %04lx, CPLD v%d.%d.%d.%d\n",
+                                       candev->chip[chipnr]->chip_base_addr,
                                                        id1>>4, id1&0x0f, id2>>4, id2&0x0f);
 
 
@@ -252,10 +247,10 @@ int bfadcan_init_chip_data(int card, int chipnr)
  * Return Value: The function always returns zero
  * File: src/bfadcan.c
  */
-int bfadcan_init_obj_data(int chipnr, int objnr)
+int bfadcan_init_obj_data(struct chip_t *chip, int objnr)
 {
-       chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr+(objnr+1)*0x10;
-       chips_p[chipnr]->msgobj[objnr]->flags=0;
+       chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
+       chip->msgobj[objnr]->flags=0;
        
        return 0;
 }
@@ -272,7 +267,7 @@ int bfadcan_init_obj_data(int chipnr, int objnr)
  * Return value: The function returns zero on success or %-ENODEV on failure
  * File: src/bfadcan.c
  */
-int bfadcan_program_irq(int card)
+int bfadcan_program_irq(struct candevice_t *candev)
 {
        return 0;
 }
diff --git a/lincan/src/can_queue.c b/lincan/src/can_queue.c
new file mode 100644 (file)
index 0000000..ad6160c
--- /dev/null
@@ -0,0 +1,650 @@
+/* can_queue.c - CAN message queues
+ * Linux CAN-bus device driver.
+ * 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.2  9 Jul 2003
+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+#include <linux/malloc.h>
+#else
+#include <linux/slab.h>
+#endif
+#include <linux/wait.h>
+#include "../include/can.h"
+#include "../include/can_queue.h"
+
+#ifdef CAN_DEBUG
+       #define DEBUGQUE(fmt,args...) printk(KERN_ERR "can_queue (debug): " fmt,\
+       ##args)
+       
+  atomic_t edge_num_cnt;
+#else
+       #define DEBUGQUE(fmt,args...)
+#endif
+
+#define CANQUE_ROUNDROB 1
+
+/**
+ * canque_fifo_flush_slots - free all ready slots from the FIFO
+ * @fifo: pointer to the FIFO structure
+ *
+ * The caller should be prepared to handle situations, when some
+ * slots are held by input or output side slots processing.
+ * These slots cannot be flushed or their processing interrupted.
+ *
+ * Return Value: The nonzero value indicates, that queue has not been
+ *     empty before the function call.
+ */
+int canque_fifo_flush_slots(struct canque_fifo_t *fifo)
+{
+       int ret;
+       unsigned long flags;
+       struct canque_slot_t *slot;
+       spin_lock_irqsave(&fifo->fifo_lock, flags);
+       slot=fifo->head;
+       *fifo->tail=fifo->flist;
+       fifo->flist=slot;
+       fifo->head=NULL;
+       fifo->tail=&fifo->head;
+       ret=canque_fifo_test_and_set_fl(fifo,EMPTY);
+       spin_unlock_irqrestore(&fifo->fifo_lock, flags);
+       return ret;
+}
+
+
+/**
+ * canque_fifo_init_slots - initialize one CAN FIFO
+ * @fifo: pointer to the FIFO structure
+ * @slotsnr: number of requested slots
+ *
+ * Return Value: The negative value indicates, that there is no memory
+ *     to allocate space for the requested number of the slots.
+ */
+int canque_fifo_init_slots(struct canque_fifo_t *fifo, int slotsnr)
+{
+       int size;
+       struct canque_slot_t *slot;
+       if(!slotsnr) slotsnr=MAX_BUF_LENGTH;
+       size=sizeof(struct canque_slot_t)*slotsnr;
+       fifo->entry=kmalloc(size,GFP_KERNEL);
+       if(!fifo->entry) return -1;
+       slot=fifo->entry;
+       fifo->flist=slot;
+       while(--slotsnr){
+               slot->next=slot+1;
+               slot++;
+       }
+       slot->next=NULL;
+       fifo->head=NULL;
+       fifo->tail=&fifo->head;
+       canque_fifo_set_fl(fifo,EMPTY);
+       return 1;
+}
+
+/**
+ * canque_fifo_done - frees slots allocated for CAN FIFO
+ * @fifo: pointer to the FIFO structure
+ */
+int canque_fifo_done(struct canque_fifo_t *fifo)
+{
+       if(fifo->entry)
+               kfree(fifo->entry);
+       fifo->entry=NULL;
+       return 1;
+}
+
+/* atomic_dec_and_test(&qedge->edge_used);
+ void atomic_inc(&qedge->edge_used);
+ list_add_tail(struct list_head *new, struct list_head *head)
+ list_for_each(edge,qends->inlist);
+ list_entry(ptr, type, member)
+*/
+
+int canque_get_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd)
+{
+       int ret=-2;
+       unsigned long flags;
+       struct canque_edge_t *edge;
+       
+       spin_lock_irqsave(&qends->ends_lock, flags);
+       if(!list_empty(&qends->inlist)){
+               edge=list_entry(qends->inlist.next,struct canque_edge_t,inpeers);
+               if(!canque_fifo_test_fl(&edge->fifo,BLOCK)&&!canque_fifo_test_fl(&edge->fifo,DEAD)){
+                       atomic_inc(&edge->edge_used);
+                       spin_unlock_irqrestore(&qends->ends_lock, flags);
+                       ret=canque_fifo_get_inslot(&edge->fifo, slotp, cmd);
+                       if(ret>0){
+                               *qedgep=edge;
+                               DEBUGQUE("canque_get_inslot cmd=%d found edge %d\n",cmd,edge->edge_num);
+                               return ret;
+
+                       }
+                       spin_lock_irqsave(&qends->ends_lock, flags);
+                       if(atomic_dec_and_test(&edge->edge_used))
+                               canque_notify_bothends(edge,CANQUEUE_NOTIFY_NOUSR);
+               }
+       }
+       spin_unlock_irqrestore(&qends->ends_lock, flags);
+       *qedgep=NULL;
+       DEBUGQUE("canque_get_inslot cmd=%d failed\n",cmd);
+       return ret;
+}
+
+int canque_get_inslot4id(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
+       int cmd, unsigned long id, int prio)
+{
+       int ret=-2;
+       unsigned long flags;
+       struct canque_edge_t *edge, *bestedge=NULL;
+       struct list_head *entry;
+       
+       spin_lock_irqsave(&qends->ends_lock, flags);
+       list_for_each(entry,&qends->inlist){
+               edge=list_entry(entry,struct canque_edge_t,inpeers);
+               if(canque_fifo_test_fl(&edge->fifo,BLOCK)||canque_fifo_test_fl(&edge->fifo,DEAD))
+                       continue;
+               if((id^edge->filtid)&edge->filtmask)
+                       continue;
+               if(bestedge){
+                       if(bestedge->filtmask){
+                               if (!edge->filtmask) continue;
+                       } else {
+                               if(edge->filtmask){
+                                       bestedge=edge;
+                                       continue;
+                               }
+                       }
+                       if(bestedge->edge_prio<edge->edge_prio){
+                               if(edge->edge_prio>prio) continue;
+                       } else {
+                               if(bestedge->edge_prio<=prio) continue;
+                       }
+               }
+               bestedge=edge;
+       }
+       if((edge=bestedge)!=NULL){
+               atomic_inc(&edge->edge_used);
+               spin_unlock_irqrestore(&qends->ends_lock, flags);
+               ret=canque_fifo_get_inslot(&edge->fifo, slotp, cmd);
+               if(ret>0){
+                       *qedgep=edge;
+                       DEBUGQUE("canque_get_inslot4id cmd=%d id=%ld prio=%d found edge %d\n",cmd,id,prio,edge->edge_num);
+                       return ret;
+               }
+               spin_lock_irqsave(&qends->ends_lock, flags);
+               if(atomic_dec_and_test(&edge->edge_used))
+                       canque_notify_bothends(edge,CANQUEUE_NOTIFY_NOUSR);
+       }
+       spin_unlock_irqrestore(&qends->ends_lock, flags);
+       *qedgep=NULL;
+       DEBUGQUE("canque_get_inslot4id cmd=%d id=%ld prio=%d failed\n",cmd,id,prio);
+       return ret;
+}
+
+
+int canque_put_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot)
+{
+       int ret;
+       unsigned long flags;
+       ret=canque_fifo_put_inslot(&qedge->fifo,slot);
+       if(ret) {
+               canque_activate_edge(qends,qedge);
+               canque_notify_outends(qedge,CANQUEUE_NOTIFY_PROC);
+       }
+       spin_lock_irqsave(&qends->ends_lock, flags);
+       if(atomic_dec_and_test(&qedge->edge_used))
+               canque_notify_bothends(qedge,CANQUEUE_NOTIFY_NOUSR);
+       spin_unlock_irqrestore(&qends->ends_lock, flags);
+       DEBUGQUE("canque_put_inslot for edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+int canque_abort_inslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot)
+{
+       int ret;
+       unsigned long flags;
+       ret=canque_fifo_abort_inslot(&qedge->fifo,slot);
+       if(ret) {
+               canque_notify_outends(qedge,CANQUEUE_NOTIFY_SPACE);
+       }
+       spin_lock_irqsave(&qends->ends_lock, flags);
+       if(atomic_dec_and_test(&qedge->edge_used))
+               canque_notify_bothends(qedge,CANQUEUE_NOTIFY_NOUSR);
+       spin_unlock_irqrestore(&qends->ends_lock, flags);
+       DEBUGQUE("canque_abort_inslot for edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg)
+{
+       int destnr=0;
+       int ret;
+       unsigned long flags;
+       struct canque_edge_t *edge;
+       struct list_head *entry;
+       struct canque_slot_t *slot;
+       
+       DEBUGQUE("canque_filter_msg2edges for msg ID %ld\n",msg->id);
+       spin_lock_irqsave(&qends->ends_lock, flags);
+       list_for_each(entry,&qends->inlist){
+               edge=list_entry(entry,struct canque_edge_t,inpeers);
+               if(canque_fifo_test_fl(&edge->fifo,BLOCK)||canque_fifo_test_fl(&edge->fifo,DEAD))
+                       continue;
+               if((msg->id^edge->filtid)&edge->filtmask)
+                       continue;
+               atomic_inc(&edge->edge_used);
+               spin_unlock_irqrestore(&qends->ends_lock, flags);
+               ret=canque_fifo_get_inslot(&edge->fifo, &slot, 0);
+               if(ret>0){
+                       slot->msg=*msg;
+                       destnr++;
+                       ret=canque_fifo_put_inslot(&edge->fifo,slot);
+                       if(ret) {
+                               canque_activate_edge(qends,edge);
+                               canque_notify_outends(edge,CANQUEUE_NOTIFY_PROC);
+                       }
+
+               }
+               spin_lock_irqsave(&qends->ends_lock, flags);
+               if(atomic_dec_and_test(&edge->edge_used))
+                       canque_notify_bothends(edge,CANQUEUE_NOTIFY_NOUSR);
+       }
+       spin_unlock_irqrestore(&qends->ends_lock, flags);
+       DEBUGQUE("canque_filter_msg2edges sent msg ID %ld to %d edges\n",msg->id,destnr);
+       return destnr;
+}
+
+int canque_test_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp)
+{
+       unsigned long flags;
+       int prio;
+       struct canque_edge_t *edge;
+       
+       spin_lock_irqsave(&qends->ends_lock, flags);
+       for(prio=CANQUEUE_PRIO_NR;--prio>=0;){
+               if(!list_empty(&qends->active[prio])){
+                       edge=list_entry(qends->active[prio].next,struct canque_edge_t,outpeers);
+                       atomic_inc(&edge->edge_used);
+                       spin_unlock_irqrestore(&qends->ends_lock, flags);
+                       *qedgep=edge;
+                       DEBUGQUE("canque_test_outslot found edge %d\n",edge->edge_num);
+                       return canque_fifo_test_outslot(&edge->fifo, slotp);
+               }
+       }
+       spin_unlock_irqrestore(&qends->ends_lock, flags);
+       *qedgep=NULL;
+       DEBUGQUE("canque_test_outslot no ready slot\n");
+       return -1;
+}
+
+int canque_free_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot)
+{
+       int ret;
+       unsigned long flags;
+       ret=canque_fifo_free_outslot(&qedge->fifo, slot);
+       if(ret&CAN_FIFOF_EMPTY){
+               canque_notify_inends(qedge,CANQUEUE_NOTIFY_EMPTY);
+       }
+       if(ret&CAN_FIFOF_FULL)
+               canque_notify_inends(qedge,CANQUEUE_NOTIFY_SPACE);
+       spin_lock_irqsave(&qends->ends_lock, flags);
+       if((ret&CAN_FIFOF_EMPTY) || CANQUE_ROUNDROB){
+               spin_lock(&qedge->fifo.fifo_lock);
+               if(canque_fifo_test_fl(&qedge->fifo,EMPTY)){
+                       list_del(&qedge->outpeers);
+                       list_add(&qedge->outpeers,&qends->idle);
+               }
+           #if CANQUE_ROUNDROB
+               else{
+                       list_del(&qedge->outpeers);
+                       list_add_tail(&qedge->outpeers,&qends->active[qedge->edge_prio]);
+               }
+           #endif /*CANQUE_ROUNDROB*/
+               spin_unlock(&qedge->fifo.fifo_lock);
+       }
+       if(atomic_dec_and_test(&qedge->edge_used))
+               canque_notify_bothends(qedge,CANQUEUE_NOTIFY_NOUSR);
+       spin_unlock_irqrestore(&qends->ends_lock, flags);
+       DEBUGQUE("canque_free_outslot for edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+int canque_again_outslot(struct canque_ends_t *qends,
+       struct canque_edge_t *qedge, struct canque_slot_t *slot)
+{
+       int ret;
+       unsigned long flags;
+       ret=canque_fifo_again_outslot(&qedge->fifo, slot);
+       if(ret&CAN_FIFOF_EMPTY){
+               canque_notify_inends(qedge,CANQUEUE_NOTIFY_EMPTY);
+       }
+       if(ret&CAN_FIFOF_FULL)
+               canque_notify_inends(qedge,CANQUEUE_NOTIFY_SPACE);
+       spin_lock_irqsave(&qends->ends_lock, flags);
+       if(atomic_dec_and_test(&qedge->edge_used))
+               canque_notify_bothends(qedge,CANQUEUE_NOTIFY_NOUSR);
+       spin_unlock_irqrestore(&qends->ends_lock, flags);
+       DEBUGQUE("canque_again_outslot for edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+int canque_set_filt(struct canque_edge_t *qedge,
+       unsigned long filtid, unsigned long filtmask)
+{
+       int ret;
+       unsigned long flags;
+
+       spin_lock_irqsave(&qedge->fifo.fifo_lock,flags);
+       atomic_inc(&qedge->edge_used);
+       qedge->filtid=filtid;
+       qedge->filtmask=filtmask;
+       if(canque_fifo_test_fl(&qedge->fifo,DEAD)) ret=-1;
+       else ret=canque_fifo_test_and_set_fl(&qedge->fifo,BLOCK)?1:0;
+
+       spin_unlock_irqrestore(&qedge->fifo.fifo_lock,flags);
+       if(ret>=0){
+               canque_notify_bothends(qedge,CANQUEUE_NOTIFY_FILTCH);
+       }
+       spin_lock_irqsave(&qedge->fifo.fifo_lock,flags);
+       if(!ret)canque_fifo_clear_fl(&qedge->fifo,BLOCK);
+       if(atomic_dec_and_test(&qedge->edge_used))
+               canque_notify_bothends(qedge,CANQUEUE_NOTIFY_NOUSR);
+       spin_unlock_irqrestore(&qedge->fifo.fifo_lock,flags);
+       
+       DEBUGQUE("canque_set_filt for edge %d, ID %ld and mask %ld returned %d\n",qedge->edge_num,filtid,filtmask,ret);
+       return ret;
+}
+
+int canque_flush(struct canque_edge_t *qedge)
+{
+       int ret;
+       unsigned long flags;
+
+       atomic_inc(&qedge->edge_used);
+       ret=canque_fifo_flush_slots(&qedge->fifo);
+       if(ret){
+               canque_notify_inends(qedge,CANQUEUE_NOTIFY_EMPTY);
+               canque_notify_inends(qedge,CANQUEUE_NOTIFY_SPACE);
+               spin_lock_irqsave(&qedge->outends->ends_lock, flags);
+               spin_lock(&qedge->fifo.fifo_lock);
+               if(canque_fifo_test_fl(&qedge->fifo,EMPTY)){
+                       list_del(&qedge->outpeers);
+                       list_add(&qedge->outpeers,&qedge->outends->idle);
+               }
+               if(atomic_dec_and_test(&qedge->edge_used))
+                       canque_notify_bothends(qedge,CANQUEUE_NOTIFY_NOUSR);
+               spin_unlock(&qedge->fifo.fifo_lock);
+               spin_unlock_irqrestore(&qedge->outends->ends_lock, flags);
+       }
+       DEBUGQUE("canque_flush for edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+int canqueue_ends_init_gen(struct canque_ends_t *qends)
+{
+       int i;
+       for(i=CANQUEUE_PRIO_NR;--i>=0;){
+               INIT_LIST_HEAD(&qends->active[i]);
+       }
+       INIT_LIST_HEAD(&qends->idle);
+       INIT_LIST_HEAD(&qends->inlist);
+       spin_lock_init(&qends->ends_lock);
+       return 0;
+}
+
+
+void canqueue_notify_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what)
+{
+       DEBUGQUE("canqueue_notify_kern for edge %d and event %d\n",qedge->edge_num,what);
+       switch(what){
+               case CANQUEUE_NOTIFY_EMPTY:
+                       wake_up_interruptible(&qends->endinfo.fileinfo.emptyq);
+                       break;
+               case CANQUEUE_NOTIFY_SPACE:
+                       wake_up_interruptible(&qends->endinfo.fileinfo.writeq);
+                       break;
+               case CANQUEUE_NOTIFY_PROC:
+                       wake_up_interruptible(&qends->endinfo.fileinfo.readq);
+                       break;
+               case CANQUEUE_NOTIFY_NOUSR:
+                       wake_up_interruptible(&qends->endinfo.fileinfo.readq);
+                       wake_up_interruptible(&qends->endinfo.fileinfo.writeq);
+                       wake_up_interruptible(&qends->endinfo.fileinfo.emptyq);
+                       break;
+               case CANQUEUE_NOTIFY_DEAD:
+                       if(atomic_read(&qedge->edge_used)>0)
+                               atomic_dec(&qedge->edge_used);
+                       break;
+               case CANQUEUE_NOTIFY_ATACH:
+                       atomic_inc(&qedge->edge_used);
+                       break;
+       }
+}
+
+int canqueue_ends_init_kern(struct canque_ends_t *qends)
+{
+       canqueue_ends_init_gen(qends);
+       qends->context=NULL;
+       init_waitqueue_head(&qends->endinfo.fileinfo.readq);
+       init_waitqueue_head(&qends->endinfo.fileinfo.writeq);
+       init_waitqueue_head(&qends->endinfo.fileinfo.emptyq);
+       qends->notify=canqueue_notify_kern;
+       DEBUGQUE("canqueue_ends_init_kern\n");
+       return 0;
+}
+
+
+int canque_get_inslot4id_wait_kern(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
+       int cmd, unsigned long id, int prio)
+{
+       int ret=-1;
+       DEBUGQUE("canque_get_inslot4id_wait_kern for cmd %d, id %ld, prio %d\n",cmd,id,prio);
+       wait_event_interruptible((qends->endinfo.fileinfo.writeq), 
+               (ret=canque_get_inslot4id(qends,qedgep,slotp,cmd,id,prio))!=-1);
+       return ret;
+}
+
+int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
+       struct canque_edge_t **qedgep, struct canque_slot_t **slotp)
+{
+       int ret=-1;
+       DEBUGQUE("canque_get_outslot_wait_kern\n");
+       wait_event_interruptible((qends->endinfo.fileinfo.readq), 
+               (ret=canque_test_outslot(qends,qedgep,slotp))!=-1);
+       return ret;
+}
+
+int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge)
+{
+       int ret=-1;
+       DEBUGQUE("canque_sync_wait_kern\n");
+       wait_event_interruptible((qends->endinfo.fileinfo.emptyq), 
+               (ret=canque_fifo_test_fl(&qedge->fifo,EMPTY)));
+       return ret;
+}
+
+
+struct canque_edge_t *canque_new_edge_kern(int slotsnr)
+{
+       struct canque_edge_t *qedge;
+       qedge = (struct canque_edge_t *)kmalloc(sizeof(struct canque_edge_t), GFP_KERNEL);
+       if(qedge == NULL) return NULL;
+
+       memset(qedge,0,sizeof(struct canque_edge_t));
+       if(canque_fifo_init_slots(&qedge->fifo, slotsnr)<0){
+               kfree(qedge);
+               DEBUGQUE("canque_new_edge_kern failed\n");
+               return NULL;
+       }
+       atomic_set(&qedge->edge_used,0);
+       qedge->filtid = 0;
+       qedge->filtmask = 0;
+       qedge->edge_prio = 0;
+    #ifdef CAN_DEBUG
+       /* not exactly clean, but enough for debugging */
+       atomic_inc(&edge_num_cnt);
+       qedge->edge_num=atomic_read(&edge_num_cnt);
+    #endif /* CAN_DEBUG */
+       DEBUGQUE("canque_new_edge_kern %d\n",qedge->edge_num);
+       return qedge;
+}
+
+int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends)
+{
+       unsigned long flags;
+       if(qedge == NULL) return -1;
+       DEBUGQUE("canqueue_connect_edge %d\n",qedge->edge_num);
+       atomic_inc(&qedge->edge_used);
+       spin_lock_irqsave(&inends->ends_lock, flags);
+       spin_lock(&outends->ends_lock);
+       spin_lock(&qedge->fifo.fifo_lock);
+       qedge->inends=inends;
+       list_add(&qedge->inpeers,&inends->inlist);
+       qedge->outends=outends;
+       list_add(&qedge->outpeers,&outends->idle);
+       spin_unlock(&qedge->fifo.fifo_lock);
+       spin_unlock(&outends->ends_lock);
+       spin_unlock_irqrestore(&inends->ends_lock, flags);
+       canque_notify_bothends(qedge, CANQUEUE_NOTIFY_ATACH);
+       
+       spin_lock_irqsave(&qedge->fifo.fifo_lock, flags);
+       if(atomic_dec_and_test(&qedge->edge_used))
+               canque_notify_bothends(qedge,CANQUEUE_NOTIFY_NOUSR);
+       spin_unlock_irqrestore(&qedge->fifo.fifo_lock, flags);
+       return 0;
+}
+
+int canqueue_disconnect_edge(struct canque_edge_t *qedge)
+{
+       int ret;
+       unsigned long flags;
+       spin_lock_irqsave(&qedge->inends->ends_lock,flags);
+       spin_lock(&qedge->outends->ends_lock);
+       spin_lock(&qedge->fifo.fifo_lock);
+       if(atomic_read(&qedge->edge_used)==0) {
+               if(qedge->outends){
+                       list_del(&qedge->outpeers);
+                       qedge->outends=NULL;
+               }
+               if(qedge->inends){
+                       list_del(&qedge->inpeers);
+                       qedge->inends=NULL;
+               }
+               ret=1;
+       } else ret=-1;
+       spin_unlock(&qedge->fifo.fifo_lock);
+       spin_unlock(&qedge->outends->ends_lock);
+       spin_unlock_irqrestore(&qedge->inends->ends_lock,flags);
+       DEBUGQUE("canqueue_disconnect_edge %d returned %d\n",qedge->edge_num,ret);
+       return ret;
+}
+
+int canqueue_disconnect_edge_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge)
+{
+       canque_fifo_set_fl(&qedge->fifo,BLOCK);
+       DEBUGQUE("canqueue_disconnect_edge_kern %d called\n",qedge->edge_num);
+       if(!canque_fifo_test_and_set_fl(&qedge->fifo,DEAD)){
+               canque_notify_bothends(qedge, CANQUEUE_NOTIFY_DEAD);
+               if(atomic_read(&qedge->edge_used)>0)
+                       atomic_dec(&qedge->edge_used);
+               DEBUGQUE("canqueue_disconnect_edge_kern %d waiting\n",qedge->edge_num);
+               wait_event_interruptible((qends->endinfo.fileinfo.emptyq), 
+                       (canqueue_disconnect_edge(qedge)>=0));
+               return 0;
+       } else {
+               DEBUGQUE("canqueue_disconnect_edge_kern failed\n");
+               return -1;
+       }
+}
+
+
+int canqueue_disconnect_list_kern(struct canque_ends_t *qends, struct list_head *list)
+{
+       struct canque_edge_t *edge;
+       unsigned long flags;
+       for(;;){
+               spin_lock_irqsave(&qends->ends_lock,flags);
+               if(list_empty(list)){
+                       spin_unlock_irqrestore(&qends->ends_lock,flags);
+                       return 0;
+               }
+               if(list == &qends->inlist)
+                       edge=list_entry(list->next,struct canque_edge_t,inpeers);
+               else
+                       edge=list_entry(list->next,struct canque_edge_t,outpeers);
+               atomic_inc(&edge->edge_used);
+               spin_unlock_irqrestore(&qends->ends_lock,flags);
+               if(canqueue_disconnect_edge_kern(qends, edge)>=0) {
+                       /* Free edge memory */
+                       canque_fifo_done(&edge->fifo);
+                       kfree(edge);
+               }else{
+                       DEBUGQUE("canqueue_disconnect_list_kern in troubles\n");
+                       DEBUGQUE("the edge %d has usage count %d and flags %ld\n",edge->edge_num,atomic_read(&edge->edge_used),edge->fifo.fifo_flags);
+                       return -1;
+               }
+       }
+}
+
+void canqueue_block_list(struct canque_ends_t *qends, struct list_head *list)
+{
+       struct canque_edge_t *edge;
+       struct list_head *entry;
+       unsigned long flags;
+       
+       spin_lock_irqsave(&qends->ends_lock, flags);
+       list_for_each(entry,&qends->inlist){
+               if(list == &qends->inlist)
+                       edge=list_entry(list->next,struct canque_edge_t,inpeers);
+               else
+                       edge=list_entry(list->next,struct canque_edge_t,outpeers);
+               canque_fifo_set_fl(&edge->fifo,BLOCK);
+               /*spin_unlock_irqrestore(&qends->ends_lock, flags);*/
+               /* Loop can be break by interrupts and preempts there */
+               /*spin_lock_irqsave(&qends->ends_lock, flags);*/
+       }
+       spin_unlock_irqrestore(&qends->ends_lock, flags);
+}
+
+
+int canqueue_ends_done_kern(struct canque_ends_t *qends, int sync)
+{
+       unsigned long flags;
+       int i;
+
+       DEBUGQUE("canqueue_ends_done_kern\n");
+       spin_lock_irqsave(&qends->ends_lock,flags);
+       canqueue_block_list(qends, &qends->idle);
+       for(i=CANQUEUE_PRIO_NR;--i>=0;){
+               canqueue_block_list(qends, &qends->active[i]);
+       }
+       canqueue_block_list(qends, &qends->idle);
+       canqueue_block_list(qends, &qends->inlist);
+       spin_unlock_irqrestore(&qends->ends_lock,flags);
+
+       for(i=CANQUEUE_PRIO_NR;--i>=0;){
+               canqueue_disconnect_list_kern(qends, &qends->active[i]);
+       }
+       canqueue_disconnect_list_kern(qends, &qends->idle);
+       canqueue_disconnect_list_kern(qends, &qends->inlist);
+
+       wake_up_interruptible(&qends->endinfo.fileinfo.readq);
+       wake_up_interruptible(&qends->endinfo.fileinfo.writeq);
+       wake_up_interruptible(&qends->endinfo.fileinfo.emptyq);
+       
+
+       return 0;
+}
+
index 8530a76..521bec7 100644 (file)
@@ -1,18 +1,13 @@
 /* cc_can104.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
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/template.c
  */
-int cc104_request_io(unsigned long io_addr)
+int cc104_request_io(struct candevice_t *candev)
 {
-       if (check_region(io_addr,IO_RANGE)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr);
+       if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
                return -ENODEV;
-       }
-       else {
-               request_region(io_addr,IO_RANGE,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + IO_RANGE - 1);
+       }else {
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
        }
        return 0;
 }
@@ -70,9 +63,9 @@ int cc104_request_io(unsigned long io_addr)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int cc104_release_io(unsigned long io_addr)
+int cc104_release_io(struct candevice_t *candev)
 {
-       release_region(io_addr,IO_RANGE);
+       can_release_io_region(candev->io_addr,IO_RANGE);
 
        return 0;
 }
@@ -87,7 +80,7 @@ int cc104_release_io(unsigned long io_addr)
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/template.c
  */
-int cc104_reset(int card)
+int cc104_reset(struct candevice_t *candev)
 {
        return 0;
 }
@@ -110,12 +103,13 @@ int cc104_reset(int card)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int cc104_init_hw_data(int card
+int cc104_init_hw_data(struct candevice_t *candev
 {
-       candevices_p[card]->res_addr=RESET_ADDR;
-       candevices_p[card]->nr_82527_chips=0;
-       candevices_p[card]->nr_sja1000_chips=1;
-       candevices_p[card]->flags |= ~PROGRAMMABLE_IRQ;
+       candev->res_addr=RESET_ADDR;
+       candev->nr_82527_chips=0;
+       candev->nr_sja1000_chips=1;
+        candev->nr_all_chips=1;
+       candev->flags &= ~PROGRAMMABLE_IRQ;
 
        return 0;
 }
@@ -150,14 +144,14 @@ int cc104_init_hw_data(int card)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int cc104_init_chip_data(int card, int chipnr)
+int cc104_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       candevices_p[card]->chip[chipnr]->chip_type=CHIP_TYPE;
-       candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->clock = 16000000;
-       candevices_p[card]->chip[chipnr]->flags = 0;
-       candevices_p[card]->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
-       candevices_p[card]->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL |
+       candev->chip[chipnr]->chip_type=CHIP_TYPE;
+       candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+       candev->chip[chipnr]->clock = 16000000;
+       candev->chip[chipnr]->flags = 0;
+       candev->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
+       candev->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL |
                                                                OCR_TX0_LH;
 
        return 0;
@@ -180,10 +174,10 @@ int cc104_init_chip_data(int card, int chipnr)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int cc104_init_obj_data(int chipnr, int objnr)
+int cc104_init_obj_data(struct chip_t *chip, int objnr)
 {
-       chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr;
-       chips_p[chipnr]->msgobj[objnr]->flags=0;
+       chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
+       chip->msgobj[objnr]->flags=0;
        
        return 0;
 }
@@ -200,7 +194,7 @@ int cc104_init_obj_data(int chipnr, int objnr)
  * Return value: The function returns zero on success or %-ENODEV on failure
  * File: src/template.c
  */
-int cc104_program_irq(int card)
+int cc104_program_irq(struct candevice_t *candev)
 {
        return 0;
 }
index 5f7d112..b1146be 100644 (file)
@@ -1,23 +1,24 @@
 /* close.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
  */
 
 #define __NO_VERSION__
 #include <linux/module.h> 
 
 #include <linux/autoconf.h>
-#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
-#define MODVERSIONS
-#endif
-
-#if defined (MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 
 #include <linux/fs.h>
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+#include <linux/malloc.h>
+#else
+#include <linux/slab.h>
+#endif
 
 #include "../include/main.h"
 #include "../include/close.h"
 
 int can_close(struct inode *inode, struct file *file)
 {
-       objects_p[MINOR_NR]->flags &= ~BUFFERS_ALLOCATED;
-       /* Give up message buffer memory */
-       if (objects_p[MINOR_NR]->fifo->buf_tx_entry)
-               del_mem_from_list(objects_p[MINOR_NR]->fifo->buf_tx_entry);
-       else
-               CANMSG("objects_p[MINOR_NR]->fifo->buf_tx_entry is NULL\n");
-       if (objects_p[MINOR_NR]->fifo->buf_rx_entry)
-               del_mem_from_list(objects_p[MINOR_NR]->fifo->buf_rx_entry);
-       else
-               CANMSG("objects_p[MINOR_NR]->fifo->buf_rx_entry is NULL\n");
-
-/* FIXME: what about clearing chip HW status, stopping sending messages etc? */
+       struct canuser_t *canuser = (struct canuser_t*)(file->private_data);
+       struct canque_ends_t *qends;
+       struct msgobj_t *obj;
+       
+       if(!canuser || (canuser->magic != CAN_USER_MAGIC)){
+               CANMSG("can_close: bad canuser magic\n");
+               return -ENODEV;
+       }
+       
+       obj = canuser->msgobj;
+       qends = canuser->qends;
+
+       list_del(&canuser->peers);
+       canqueue_ends_done_kern(qends, 1);
+       canuser->qends = NULL;
+       kfree(qends);
+
+       kfree(canuser);
+
+       if(atomic_dec_and_test(&obj->obj_used)){
+               obj->flags &= ~OBJ_OPENED;
+               /* FIXME: what about clearing chip HW status, stopping sending messages etc? */
+       };
        
-       objects_p[MINOR_NR]->flags &= ~OPENED;
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,50))
        MOD_DEC_USE_COUNT;
 #endif
diff --git a/lincan/src/devcommon.c b/lincan/src/devcommon.c
new file mode 100644 (file)
index 0000000..9cd29d0
--- /dev/null
@@ -0,0 +1,66 @@
+/* devcommon.c - common device code
+ * Linux CAN-bus device driver.
+ * 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.2  9 Jul 2003
+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+#include <linux/malloc.h>
+#else
+#include <linux/slab.h>
+#endif
+#include <linux/wait.h>
+#include "../include/can.h"
+#include "../include/can_queue.h"
+#include "../include/main.h"
+#include "../include/devcommon.h"
+
+void canqueue_notify_chip(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what)
+{
+       struct chip_t *chip=qends->endinfo.chipinfo.chip;
+       struct msgobj_t *obj=qends->endinfo.chipinfo.msgobj;
+
+       DEBUGMSG("canqueue_notify_chip for edge %d and event %d\n",qedge->edge_num,what);
+       switch(what){
+               /*case CANQUEUE_NOTIFY_EMPTY:*/
+               /*case CANQUEUE_NOTIFY_SPACE:*/
+               /*case CANQUEUE_NOTIFY_NOUSR:
+                       wake_up_interruptible(&qends->endinfo.chipinfo.daemonq);
+                       break;*/
+               case CANQUEUE_NOTIFY_PROC:
+                       /*wake_up_interruptible(&qends->endinfo.chipinfo.daemonq);*/
+                       chip->chipspecops->wakeup_tx(chip, obj);
+                       break;
+               case CANQUEUE_NOTIFY_DEAD:
+                       if(atomic_read(&qedge->edge_used)>0)
+                               atomic_dec(&qedge->edge_used);
+                       break;
+               case CANQUEUE_NOTIFY_ATACH:
+                       atomic_inc(&qedge->edge_used);
+                       break;
+       }
+}
+
+
+int canqueue_ends_init_chip(struct canque_ends_t *qends, struct chip_t *chip, struct msgobj_t *obj)
+{
+       int ret;
+       ret=canqueue_ends_init_gen(qends);
+       if(ret<0) return ret;
+       
+       qends->context=NULL;
+       init_waitqueue_head(&qends->endinfo.chipinfo.daemonq);
+       qends->endinfo.chipinfo.chip=chip;
+       qends->endinfo.chipinfo.msgobj=obj;
+       qends->notify=canqueue_notify_chip;
+
+       DEBUGMSG("canqueue_ends_init_chip\n");
+       return 0;
+}
+
+
index 5ab2dcf..c10db6b 100644 (file)
@@ -1,31 +1,50 @@
 /* i82527.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
  */
 
 #define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/autoconf.h>
-#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
-#define MODVERSIONS
-#endif
-
-#if defined (MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 
+#include <linux/sched.h>
 #include <linux/fs.h>
 
 #include "../include/main.h"
 #include "../include/i82527.h"
 
+void i82527_irq_rtr_handler(struct chip_t *chip, struct msgobj_t *obj, 
+                           struct rtr_id *rtr_search, unsigned long message_id);
+
+
 extern int stdmask;
 extern int extmask;
 extern int mo15mask;
 
+/* helper functions for segmented cards read and write configuration and status registers
+   above 0xf offset */
+
+void i82527_seg_write_reg(const struct chip_t *chip, unsigned char data, unsigned address)
+{
+       if((address > 0xf) && (chip->flags & CHIP_SEGMENTED))
+               canobj_write_reg(chip, chip->msgobj[(address>>4)-1],data, address & 0xf);
+       else
+               can_write_reg(chip, data, address);
+}
+
+unsigned i82527_seg_read_reg(const struct chip_t *chip, unsigned address)
+{
+       if((address > 0xf) && (chip->flags & CHIP_SEGMENTED))
+               return canobj_read_reg(chip, chip->msgobj[(address>>4)-1], address & 0xf);
+       else
+               return can_read_reg(chip, address);
+}
+
 int i82527_enable_configuration(struct chip_t *chip)
 {
        unsigned short flags=0;
@@ -50,19 +69,19 @@ int i82527_chip_config(struct chip_t *chip)
 {
        can_write_reg(chip,chip->int_cpu_reg,iCPU); // Configure cpu interface
        can_write_reg(chip,(iCTL_CCE|iCTL_INI),iCTL); // Enable configuration
-       can_write_reg(chip,chip->int_clk_reg,iCLK); // Set clock out slew rates 
-       can_write_reg(chip,chip->int_bus_reg,iBUS); /* Bus configuration */
+       i82527_seg_write_reg(chip,chip->int_clk_reg,iCLK); // Set clock out slew rates 
+       i82527_seg_write_reg(chip,chip->int_bus_reg,iBUS); /* Bus configuration */
        can_write_reg(chip,0x00,iSTAT); /* Clear error status register */
 
        /* Check if we can at least read back some arbitrary data from the 
         * card. If we can not, the card is not properly configured!
         */
-       can_write_reg(chip,0x25,MSG_OFFSET(1)+iMSGDAT1);
-       can_write_reg(chip,0x52,MSG_OFFSET(2)+iMSGDAT3);
-       can_write_reg(chip,0xc3,MSG_OFFSET(10)+iMSGDAT6);
-       if ( (can_read_reg(chip,MSG_OFFSET(1)+iMSGDAT1) != 0x25) ||
-             (can_read_reg(chip,MSG_OFFSET(2)+iMSGDAT3) != 0x52) ||
-             (can_read_reg(chip,MSG_OFFSET(10)+iMSGDAT6) != 0xc3) ) {
+       canobj_write_reg(chip,chip->msgobj[1],0x25,iMSGDAT1);
+       canobj_write_reg(chip,chip->msgobj[2],0x52,iMSGDAT3);
+       canobj_write_reg(chip,chip->msgobj[10],0xc3,iMSGDAT6);
+       if ( (canobj_read_reg(chip,chip->msgobj[1],iMSGDAT1) != 0x25) ||
+             (canobj_read_reg(chip,chip->msgobj[2],iMSGDAT3) != 0x52) ||
+             (canobj_read_reg(chip,chip->msgobj[10],iMSGDAT6) != 0xc3) ) {
                CANMSG("Could not read back from the hardware.\n");
                CANMSG("This probably means that your hardware is not correctly configured!\n");
                return -1;
@@ -160,7 +179,7 @@ int i82527_baud_rate(struct chip_t *chip, int rate, int clock, int sjw,
                                        (100*(best_tseg-tseg2)/(best_tseg+1)));
                                        
                                
-       can_write_reg(chip, sjw<<6 | best_brp, iBT0);
+       i82527_seg_write_reg(chip, sjw<<6 | best_brp, iBT0);
        can_write_reg(chip, ((flags & BTR1_SAM) != 0)<<7 | tseg2<<4 | tseg1,
                                                                iBT1);
        DEBUGMSG("Writing 0x%x to iBT0\n",(sjw<<6 | best_brp));
@@ -230,24 +249,24 @@ int i82527_message15_mask(struct chip_t *chip, unsigned long code, unsigned long
 int i82527_clear_objects(struct chip_t *chip)
 {
        int i=0,id=0,data=0;
+       struct msgobj_t *obj;
 
        DEBUGMSG("Cleared all message objects on chip\n");
 
        for (i=1; i<=15; i++) {
-               can_write_reg(chip,(INTPD_RES|RXIE_RES|TXIE_RES|MVAL_RES) ,
-                                                       MSG_OFFSET(i)+iMSGCTL0);
-               can_write_reg(chip,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES) ,
-                                                       MSG_OFFSET(i)+iMSGCTL1);
+               obj=chip->msgobj[i];
+               canobj_write_reg(chip,obj,(INTPD_RES|RXIE_RES|TXIE_RES|MVAL_RES),iMSGCTL0);
+               canobj_write_reg(chip,obj,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES), iMSGCTL1);
                for (data=0x07; data<0x0f; data++)
-                       can_write_reg(chip,0x00,MSG_OFFSET(i)+data);
+                       canobj_write_reg(chip,obj,0x00,data);
                for (id=2; id<6; id++) {
-                       can_write_reg(chip,0x00,MSG_OFFSET(i)+id);
+                       canobj_write_reg(chip,obj,0x00,id);
                }
                if (extended==0) {
-                       can_write_reg(chip,0x00,MSG_OFFSET(i)+iMSGCFG);
+                       canobj_write_reg(chip,obj,0x00,iMSGCFG);
                }
                else {
-                       can_write_reg(chip,MCFG_XTD,MSG_OFFSET(i)+iMSGCFG);
+                       canobj_write_reg(chip,obj,MCFG_XTD,iMSGCFG);
                }
        }
        if (extended==0)
@@ -268,56 +287,49 @@ int i82527_config_irqs(struct chip_t *chip, short irqs)
 int i82527_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
 {
        if (extended) {
-               can_write_reg(chip,MCFG_XTD,MSG_OFFSET(obj->object)+iMSGCFG);
+               canobj_write_reg(chip,obj,MCFG_XTD,iMSGCFG);
        }
        else {
-               can_write_reg(chip,0x00,MSG_OFFSET(obj->object)+iMSGCFG);
+               canobj_write_reg(chip,obj,0x00,iMSGCFG);
        }
-       can_write_reg(chip ,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES),
-                                       MSG_OFFSET(obj->object)+iMSGCTL1);
-       can_write_reg(chip ,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),
-                                       MSG_OFFSET(obj->object)+iMSGCTL0);
+       canobj_write_reg(chip,obj,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES), iMSGCTL1);
+       canobj_write_reg(chip,obj,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),iMSGCTL0);
        
        return 0;
 }
 
-int i82527_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, 
+int i82527_pre_write_config(struct chip_t *chip, struct msgobj_t *obj,
                                                        struct canmsg_t *msg)
 {
        int i=0,id0=0,id1=0,id2=0,id3=0;
 
-       can_write_reg(chip,(RMPD_RES|TXRQ_RES|CPUU_SET|NEWD_RES),
-                                       MSG_OFFSET(obj->object)+iMSGCTL1);
-       can_write_reg(chip,(MVAL_SET|TXIE_SET|RXIE_RES|INTPD_RES),
-                                       MSG_OFFSET(obj->object)+iMSGCTL0);
+       canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|CPUU_SET|NEWD_RES),iMSGCTL1);
+       canobj_write_reg(chip,obj,(MVAL_SET|TXIE_SET|RXIE_RES|INTPD_RES),iMSGCTL0);
        if (extended) {
-               can_write_reg(chip,(msg->length<<4)+(MCFG_DIR|MCFG_XTD),
-                                       MSG_OFFSET(obj->object)+iMSGCFG);
+               canobj_write_reg(chip,obj,(msg->length<<4)+(MCFG_DIR|MCFG_XTD),iMSGCFG);
        }
        else {
-               can_write_reg(chip,(msg->length<<4)+MCFG_DIR,
-                                       MSG_OFFSET(obj->object)+iMSGCFG);
+               canobj_write_reg(chip,obj,(msg->length<<4)+MCFG_DIR,iMSGCFG);
        }
        if (extended) {
                id0 = (unsigned char) (msg->id<<3);
                id1 = (unsigned char) (msg->id>>5);
                id2 = (unsigned char) (msg->id>>13);
                id3 = (unsigned char) (msg->id>>21);
-               can_write_reg(chip,id0,MSG_OFFSET(obj->object)+iMSGID3);
-               can_write_reg(chip,id1,MSG_OFFSET(obj->object)+iMSGID2);
-               can_write_reg(chip,id2,MSG_OFFSET(obj->object)+iMSGID1);
-               can_write_reg(chip,id3,MSG_OFFSET(obj->object)+iMSGID0);
+               canobj_write_reg(chip,obj,id0,iMSGID3);
+               canobj_write_reg(chip,obj,id1,iMSGID2);
+               canobj_write_reg(chip,obj,id2,iMSGID1);
+               canobj_write_reg(chip,obj,id3,iMSGID0);
        }
        else {
                id1 = (unsigned char) (msg->id<<5);
                id0 = (unsigned char) (msg->id>>3);
-               can_write_reg(chip,id1,MSG_OFFSET(obj->object)+iMSGID1);
-               can_write_reg(chip,id0,MSG_OFFSET(obj->object)+iMSGID0);
+               canobj_write_reg(chip,obj,id1,iMSGID1);
+               canobj_write_reg(chip,obj,id0,iMSGID0);
        }
-       can_write_reg(chip,0xfa,MSG_OFFSET(obj->object)+iMSGCTL1);
+       canobj_write_reg(chip,obj,0xfa,iMSGCTL1);
        for (i=0; i<msg->length; i++) {
-               can_write_reg(chip,msg->data[i],MSG_OFFSET(obj->object)+
-                                                               iMSGDAT0+i);
+               canobj_write_reg(chip,obj,msg->data[i],iMSGDAT0+i);
        }
 
        return 0;
@@ -327,12 +339,10 @@ int i82527_send_msg(struct chip_t *chip, struct msgobj_t *obj,
                                                        struct canmsg_t *msg)
 {
        if (msg->flags & MSG_RTR) {
-               can_write_reg(chip,(RMPD_RES|TXRQ_RES|CPUU_RES|NEWD_SET),
-                                       MSG_OFFSET(obj->object)+iMSGCTL1);
+               canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|CPUU_RES|NEWD_SET),iMSGCTL1);
        }
        else {
-               can_write_reg(chip,(RMPD_RES|TXRQ_SET|CPUU_RES|NEWD_SET),
-                                       MSG_OFFSET(obj->object)+iMSGCTL1);
+               canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_SET|CPUU_RES|NEWD_SET),iMSGCTL1);
        }
 
        return 0;
@@ -352,10 +362,8 @@ int i82527_check_tx_stat(struct chip_t *chip)
 
 int i82527_remote_request(struct chip_t *chip, struct msgobj_t *obj)
 {
-       can_write_reg(chip, (MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES), 
-                                       MSG_OFFSET(obj->object)+iMSGCTL0);
-       can_write_reg(chip, (RMPD_RES|TXRQ_SET|MLST_RES|NEWD_RES), 
-                                       MSG_OFFSET(obj->object)+iMSGCTL1);
+       canobj_write_reg(chip,obj,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),iMSGCTL0);
+       canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_SET|MLST_RES|NEWD_RES),iMSGCTL1);
        
        return 0;
 }
@@ -366,8 +374,8 @@ int i82527_set_btregs(struct chip_t *chip, unsigned short btr0,
        if (i82527_enable_configuration(chip))
                return -ENODEV;
 
-       can_write_reg(chip, btr0, iBT0);
-       can_write_reg(chip, btr1, iBT1);
+       i82527_seg_write_reg(chip, btr0, iBT0);
+       i82527_seg_write_reg(chip, btr1, iBT1);
 
        i82527_disable_configuration(chip);
 
@@ -394,6 +402,187 @@ int i82527_stop_chip(struct chip_t *chip)
        return 0;
 }
 
+inline void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
+{
+       int cmd;
+
+       canobj_write_reg(chip,obj,(MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),+iMSGCTL0);
+
+       if(obj->tx_slot){
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+       }
+
+       cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
+       if(cmd<0)
+               return;
+
+       if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
+               obj->ret = -1;
+               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+               return;
+       }
+       if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
+               obj->ret = -1;
+               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+               return;
+       } 
+}
+
+inline void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj,
+                                   unsigned long message_id)
+{
+       int i=0, tmp=1 ;
+       
+       while (tmp) {
+               canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|MLST_RES|NEWD_RES),iMSGCTL1);
+               canobj_write_reg(chip,obj,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),iMSGCTL0);
+
+               obj->rx_msg.length =(canobj_read_reg(chip,obj,iMSGCFG) & 0xf0) >> 4;
+               obj->rx_msg.id = message_id;
+               for (i=0; i < obj->rx_msg.length; i++)
+                       obj->rx_msg.data[i] = canobj_read_reg(chip,obj,iMSGDAT0+i);
+
+//FIXME: Add buffer overflow check, currently it's silently over written!
+
+               canque_filter_msg2edges(obj->qends, &obj->rx_msg);
+
+               if (!((tmp=canobj_read_reg(chip,obj,iMSGCTL1)) & NEWD_SET)) {
+                       break;
+               }
+
+               if (tmp & MLST_SET)
+                       CANMSG("Message lost!\n");
+
+       }
+}
+
+irqreturn_t i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       int id0=0, id1=0, id2=0, id3=0;
+
+       unsigned irq_register;
+       unsigned object;
+       struct chip_t *chip=(struct chip_t *)dev_id;
+       struct msgobj_t *obj;
+       unsigned long message_id;
+       struct rtr_id *rtr_search;
+
+       /*put_reg=device->hwspecops->write_register;*/
+       /*get_reg=device->hwspecops->read_register;*/
+
+       irq_register = i82527_seg_read_reg(chip, iIRQ);
+
+       while (irq_register) {
+
+               if (irq_register == 0x01) {
+                       DEBUGMSG("Status register: 0x%x\n",can_read_reg(chip, iSTAT));
+                       return IRQ_NONE;
+               }
+               
+               if (irq_register == 0x02)
+                       object = 14;
+               else
+                       object = irq_register-3;
+
+               obj=chip->msgobj[object];
+
+               if (canobj_read_reg(chip,obj,iMSGCFG) & MCFG_DIR) {
+                       set_bit(OBJ_TX_REQUEST,&obj->flags);
+                       while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){
+                               clear_bit(OBJ_TX_REQUEST,&obj->flags);
+
+                               if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES)
+                                       i82527_irq_write_handler(chip, obj); 
+
+                               clear_bit(OBJ_TX_LOCK,&obj->flags);
+                               if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break;
+                       }
+               }
+               else { 
+
+                       if (extended) {
+                               id0=canobj_read_reg(chip,obj,iMSGID3);
+                               id1=canobj_read_reg(chip,obj,iMSGID2)<<8;
+                               id2=canobj_read_reg(chip,obj,iMSGID1)<<16;
+                               id3=canobj_read_reg(chip,obj,iMSGID0)<<24;
+                               message_id=(id0|id1|id2|id3)>>3;
+                       }
+                       else {
+                               id0=canobj_read_reg(chip,obj,iMSGID1);
+                               id1=canobj_read_reg(chip,obj,iMSGID0)<<8;
+                               message_id=(id0|id1)>>5;
+                       }
+
+                       spin_lock(&hardware_p->rtr_lock);
+                       rtr_search=hardware_p->rtr_queue;
+                       while (rtr_search != NULL) {
+                               if (rtr_search->id == message_id)
+                                       break;
+                               rtr_search=rtr_search->next;
+                       }
+                       spin_unlock(&hardware_p->rtr_lock);
+                       if ((rtr_search!=NULL) && (rtr_search->id==message_id))
+                               i82527_irq_rtr_handler(chip, obj, rtr_search, message_id);
+                       else
+                               i82527_irq_read_handler(chip, obj, message_id); 
+               }
+
+               irq_register=i82527_seg_read_reg(chip, iIRQ);
+       }
+       return IRQ_HANDLED;
+}
+
+void i82527_irq_rtr_handler(struct chip_t *chip, struct msgobj_t *obj,
+                           struct rtr_id *rtr_search, unsigned long message_id)
+{
+       short int i=0;
+
+       canobj_write_reg(chip,obj,(MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),iMSGCTL0);
+       canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|MLST_RES|NEWD_RES),iMSGCTL1);
+       
+       spin_lock(&hardware_p->rtr_lock);
+
+       rtr_search->rtr_message->id=message_id;
+       rtr_search->rtr_message->length=(canobj_read_reg(chip,obj,iMSGCFG) & 0xf0)>>4;
+       for (i=0; i<rtr_search->rtr_message->length; i++)
+               rtr_search->rtr_message->data[i]=canobj_read_reg(chip,obj,iMSGDAT0+i);
+       
+       spin_unlock(&hardware_p->rtr_lock);
+
+       if (waitqueue_active(&rtr_search->rtr_wq))
+               wake_up_interruptible(&rtr_search->rtr_wq);
+}
+
+int i82527_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj)
+{
+        /* dummy lock to prevent preemption fully portable way */
+       spinlock_t dummy_lock;
+       
+       /*  preempt_disable() */
+       spin_lock_init(&dummy_lock);
+       spin_lock(&dummy_lock);
+       
+       set_bit(OBJ_TX_REQUEST,&obj->flags);
+       while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){
+               clear_bit(OBJ_TX_REQUEST,&obj->flags);
+
+               if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES)
+                       i82527_irq_write_handler(chip, obj);
+       
+               clear_bit(OBJ_TX_LOCK,&obj->flags);
+               if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break;
+       }
+
+       /* preempt_enable(); */
+       spin_unlock(&dummy_lock);
+       return 0;
+}
+
 int i82527_register(struct chipspecops_t *chipspecops)
 {
        chipspecops->chip_config = i82527_chip_config;
@@ -407,11 +596,13 @@ int i82527_register(struct chipspecops_t *chipspecops)
        chipspecops->pre_write_config = i82527_pre_write_config;
        chipspecops->send_msg = i82527_send_msg;
        chipspecops->check_tx_stat = i82527_check_tx_stat;
+       chipspecops->wakeup_tx = i82527_wakeup_tx;
        chipspecops->remote_request = i82527_remote_request;
        chipspecops->enable_configuration = i82527_enable_configuration;
        chipspecops->disable_configuration = i82527_disable_configuration;
        chipspecops->set_btregs = i82527_set_btregs;
        chipspecops->start_chip = i82527_start_chip;
        chipspecops->stop_chip = i82527_stop_chip;
+       chipspecops->irq_handler = i82527_irq_handler;
        return 0;
 }
index ec029ab..40a4204 100644 (file)
@@ -1,22 +1,18 @@
 /* ioctl.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
 
 #include <linux/fs.h>
 #include <linux/version.h>
 #include <linux/string.h>
+#include <asm/uaccess.h>
 
 #include "../include/main.h"
 #include "../include/ioctl.h"
@@ -27,16 +23,25 @@ int can_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
        int i=0;
        unsigned short channel=0;
        unsigned btr0=0, btr1=0;
+       struct canuser_t *canuser = (struct canuser_t*)(file->private_data);
        struct msgobj_t *obj;
-       struct chip_t *chip = objects_p[MINOR_NR]->hostchip;
-       struct canfifo_t *fifo = objects_p[MINOR_NR]->fifo;
-
-       /* Initialize hardware pointers */
-       if ( (obj = objects_p[MINOR_NR]) == NULL) {
+       struct chip_t *chip;
+       struct canque_ends_t *qends;
+       
+       if(!canuser || (canuser->magic != CAN_USER_MAGIC)){
+               CANMSG("can_close: bad canuser magic\n");
+               return -ENODEV;
+       }
+       
+       obj = canuser->msgobj;
+       if (obj == NULL) {
                CANMSG("Could not assign buffer structure\n");
                return -1;
        }
-       if ( (chip = obj->hostchip) == NULL) {
+
+       qends = canuser->qends;
+       chip = obj->hostchip;
+       if (chip == NULL) {
                CANMSG("Device is not correctly configured.\n");
                CANMSG("Please reload the driver.\n");
                return -1;
@@ -49,60 +54,58 @@ int can_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
                        break;
                }
                case CMD_START: {
-                       if (chips_p[arg]->chipspecops->start_chip(chip))
+                       if (chip->chipspecops->start_chip(chip))
                                return -1;
                        break;
                }
                case CMD_STOP: {
-                       if (chips_p[arg]->chipspecops->stop_chip(chip))
+                       if (chip->chipspecops->stop_chip(chip))
                                return -1;
                        break;
                }
                case CONF_FILTER: {
+                   #if 0
                        if (!strcmp(chip->chip_type,"i82527")) {
                        
                                unsigned char id1, id0;
                                id1 = (unsigned char) (arg << 5);
                                id0 = (unsigned char) (arg >> 3);
 
-                               DEBUGMSG("configuring ID=%lx in message object:
-                                                %02x, %02x\n", arg, id0, id1);
+                               DEBUGMSG("configuring ID=%lx in message object:"
+                                       " %02x, %02x\n", arg, id0, id1);
                                can_write_reg(chip,id1,MSG_OFFSET(obj->object) +
                                                                iMSGID1);
                                can_write_reg(chip,id0,MSG_OFFSET(obj->object) +
                                                                iMSGID0);
                        }
+                   #endif
 
                        /* In- and output buffer re-initialization */
                        
-                       fifo->tx_readp = fifo->buf_tx_entry;
-                       fifo->tx_writep = fifo->buf_tx_entry;
-                       fifo->rx_readp = fifo->buf_rx_entry;
-                       fifo->rx_writep = fifo->buf_rx_entry;
-                       fifo->rx_size= MAX_BUF_LENGTH * sizeof(struct canmsg_t);
-                       fifo->tx_size = fifo->rx_size;
-
-                       #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
-                               init_waitqueue(&fifo->readq);
-                               init_waitqueue(&fifo->writeq);
-                       #else
-                               init_waitqueue_head(&fifo->readq);
-                               init_waitqueue_head(&fifo->writeq);
-                       #endif
-
-                       fifo->rx_in_progress = 0;
-                       fifo->tx_in_progress = 0;
+                       if(canuser->rx_edge0){
+                               canque_set_filt(canuser->rx_edge0, arg, ~0);
+                               canque_flush(canuser->rx_edge0);
+                       }
 
                        break;
                }
+               
+               case CONF_FILTER_QUE0: {
+                       struct canfilt_t canfilt;
+                       copy_from_user(&canfilt, (void*)arg, sizeof(struct canfilt_t));
+                       if(canuser->rx_edge0){
+                               canque_set_filt(canuser->rx_edge0, canfilt.id, canfilt.mask);
+                               canque_flush(canuser->rx_edge0);
+                       }
+                       break;
+               }
 
                case CONF_BAUD: {
                        channel = arg & 0xff;
                        btr0 = (arg >> 8) & 0xff;
                        btr1 = (arg >> 16) & 0xff;
 
-                       if (chips_p[channel]->chipspecops->set_btregs(chip,
-                                                               btr0, btr1)) {
+                       if (chip->chipspecops->set_btregs(chip, btr0, btr1)) {
                                CANMSG("Error setting bit timing registers\n");
                                return -1;
                        }
index caf0ac6..1623ce8 100644 (file)
@@ -1,18 +1,13 @@
 /* irq.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 
 
 #include <linux/sched.h>
 #include <linux/version.h>
 
 #include "../include/main.h"
 #include "../include/irq.h"
-#include "../include/i82527.h"
-#include "../include/sja1000.h"
-
-void i82527_irq_rtr_handler(struct chip_t *chip, struct msgobj_t *msgobj, 
-                           struct rtr_id *rtr_search, unsigned long message_id);
-void sja1000_irq_read_handler(struct chip_t *chip, struct msgobj_t *msgobj);
-void sja1000_irq_write_handler(struct chip_t *chip, struct msgobj_t *msgobj);
-
-/*struct candevice_t *device=NULL;
-unsigned object=0,irq_register=0;
-unsigned long msgbase=0;
-struct canfifo_t *fifo=NULL;
-unsigned long message_id=0;
-struct rtr_id *rtr_search;
-*/
-
-inline void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *msgobj)
-{
-       struct canfifo_t *fifo=msgobj->fifo;
-       unsigned long msgbase=msgobj->obj_base_addr;
-       void (*write_reg)(unsigned char data, unsigned long address);
-       unsigned (*read_reg)(unsigned long address);
-       write_reg=chip->hostdevice->hwspecops->write_register;
-       read_reg=chip->hostdevice->hwspecops->read_register;
-
-       (*write_reg)((MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),msgbase+iMSGCTL0);
-
-       fifo->tx_readp++;
-       if (fifo->tx_readp >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
-               fifo->tx_readp = fifo->buf_tx_entry;
-       if (fifo->tx_readp == fifo->tx_writep) { // Output buffer is empty
-               fifo->tx_in_progress = 0;
-               if (waitqueue_active(&fifo->writeq)) {
-                       msgobj->ret = 0;
-                       wake_up_interruptible(&fifo->writeq);
-               }
-               return;
-       }
-       if (chip->chipspecops->pre_write_config(chip, msgobj, fifo->tx_readp)) {
-               if (waitqueue_active(&fifo->writeq)) {
-                       msgobj->ret = -1;
-                       wake_up_interruptible(&fifo->writeq);
-                       return;
-               }
-       }
-       if (chip->chipspecops->send_msg(chip, msgobj, fifo->tx_readp)) {
-               if (waitqueue_active(&fifo->writeq)) {
-                       msgobj->ret = -1;
-                       wake_up_interruptible(&fifo->writeq);
-                       return;
-               }
-       } 
-}
-
-inline void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *msgobj,
-                                   unsigned long message_id)
-{
-       int i=0, tmp=1 ;
-       struct canfifo_t *fifo=msgobj->fifo;
-       unsigned long msgbase=msgobj->obj_base_addr;
-       void (*write_reg)(unsigned char data, unsigned long address);
-       unsigned (*read_reg)(unsigned long address);
-       write_reg=chip->hostdevice->hwspecops->write_register;
-       read_reg=chip->hostdevice->hwspecops->read_register;
-       
-       while (tmp) {
-               (*write_reg)((RMPD_RES|TXRQ_RES|MLST_RES|NEWD_RES), msgbase +
-                                                               iMSGCTL1);
-               (*write_reg)((MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES), msgbase +
-                                                               iMSGCTL0);
-
-               fifo->rx_writep->length =((*read_reg)(msgbase+iMSGCFG) & 0xf0) >> 4;
-               fifo->rx_writep->id = message_id;
-               for (i=0; i < fifo->rx_writep->length; i++)
-                       fifo->rx_writep->data[i] = (*read_reg)(msgbase+iMSGDAT0+i);
-
-//FIXME: Add buffer overflow check, currently it's silently over written!
-
-               fifo->rx_writep++;
-               if (fifo->rx_writep >= fifo->buf_rx_entry + MAX_BUF_LENGTH)
-                       fifo->rx_writep = fifo->buf_rx_entry;
-
-               if (!((tmp=(*read_reg)(msgbase + iMSGCTL1)) & NEWD_SET)) {
-                       break;
-               }
-
-               if (tmp & MLST_SET)
-                       CANMSG("Message lost!\n");
-
-       }
-       if (waitqueue_active(&fifo->readq)) {
-               wake_up_interruptible(&fifo->readq);
-       }
-}
-
-void i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
-       int id0=0, id1=0, id2=0, id3=0;
-
-       unsigned irq_register;
-       unsigned object;
-       struct chip_t *chip=(struct chip_t *)dev_id;
-       struct msgobj_t *msgobj;
-       unsigned long msgbase;
-       unsigned long message_id;
-       struct rtr_id *rtr_search;
-       void (*write_reg)(unsigned char data, unsigned long address);
-       unsigned (*read_reg)(unsigned long address);
-       write_reg=chip->hostdevice->hwspecops->write_register;
-       read_reg=chip->hostdevice->hwspecops->read_register;
-
-       /*put_reg=device->hwspecops->write_register;*/
-       /*get_reg=device->hwspecops->read_register;*/
-
-       if ( (chip->flags & SEGMENTED) != 0)
-               irq_register = can_read_reg(chip, iIRQ+SPACING);
-       else 
-               irq_register = can_read_reg(chip, iIRQ);
-
-       while (irq_register) {
-
-               if (irq_register == 0x01) {
-                       DEBUGMSG("Status register: 0x%x\n",can_read_reg(chip, iSTAT));
-                       return;
-               }
-               
-               if (irq_register == 0x02)
-                       object = 14;
-               else
-                       object = irq_register-3;
-
-               msgobj=chip->msgobj[object];
-               msgbase=msgobj->obj_base_addr;
-
-               if ((*read_reg)(msgbase+iMSGCFG) & MCFG_DIR) {
-                       i82527_irq_write_handler(chip, msgobj); 
-               }
-               else { 
-
-                       if (extended) {
-                               id0=(*read_reg)(msgbase+iMSGID3);
-                               id1=(*read_reg)(msgbase+iMSGID2)<<8;
-                               id2=(*read_reg)(msgbase+iMSGID1)<<16;
-                               id3=(*read_reg)(msgbase+iMSGID0)<<24;
-                               message_id=(id0|id1|id2|id3)>>3;
-                       }
-                       else {
-                               id0=(*read_reg)(msgbase+iMSGID1);
-                               id1=(*read_reg)(msgbase+iMSGID0)<<8;
-                               message_id=(id0|id1)>>5;
-                       }
 
-                       spin_lock(&hardware_p->rtr_lock);
-                       rtr_search=hardware_p->rtr_queue;
-                       while (rtr_search != NULL) {
-                               if (rtr_search->id == message_id)
-                                       break;
-                               rtr_search=rtr_search->next;
-                       }
-                       spin_unlock(&hardware_p->rtr_lock);
-                       if ((rtr_search!=NULL) && (rtr_search->id==message_id))
-                               i82527_irq_rtr_handler(chip, msgobj, rtr_search, message_id);
-                       else
-                               i82527_irq_read_handler(chip, msgobj, message_id); 
-               }
-
-               if ( (chip->flags & SEGMENTED) != 0)
-                       irq_register=can_read_reg(chip, iIRQ+SPACING);
-               else
-                       irq_register=can_read_reg(chip, iIRQ);
-       }
-       
-}
-
-void i82527_irq_rtr_handler(struct chip_t *chip, struct msgobj_t *msgobj,
-                           struct rtr_id *rtr_search, unsigned long message_id)
-{
-       short int i=0;
-       unsigned long msgbase=msgobj->obj_base_addr;
-       void (*write_reg)(unsigned char data, unsigned long address);
-       unsigned (*read_reg)(unsigned long address);
-       write_reg=chip->hostdevice->hwspecops->write_register;
-       read_reg=chip->hostdevice->hwspecops->read_register;
-
-       (*write_reg)((MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),msgbase + iMSGCTL0);
-       (*write_reg)((RMPD_RES|TXRQ_RES|MLST_RES|NEWD_RES),msgbase + iMSGCTL1);
-       
-       spin_lock(&hardware_p->rtr_lock);
-
-       rtr_search->rtr_message->id=message_id;
-       rtr_search->rtr_message->length=((*read_reg)(msgbase + iMSGCFG) & 0xf0)>>4;
-       for (i=0; i<rtr_search->rtr_message->length; i++)
-               rtr_search->rtr_message->data[i]=(*read_reg)(msgbase+iMSGDAT0+i);
-       
-       spin_unlock(&hardware_p->rtr_lock);
-
-       if (waitqueue_active(&rtr_search->rtr_wq))
-               wake_up_interruptible(&rtr_search->rtr_wq);
-}
-
-void sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
-       unsigned irq_register;
-       struct chip_t *chip=(struct chip_t *)dev_id;
-       struct msgobj_t *msgobj;
-       struct canfifo_t *fifo;
-
-       irq_register=can_read_reg(chip, SJAIR);
-//     DEBUGMSG("sja1000_irq_handler: SJAIR:%02x\n",irq_register);
-//     DEBUGMSG("sja1000_irq_handler: SJASR:%02x\n",
-//                                     can_read_reg(chip, SJASR));
-
-       if ((irq_register & (IR_WUI|IR_DOI|IR_EI|IR_TI|IR_RI)) == 0)
-               return;
-
-       msgobj=chip->msgobj[0];
-       fifo=msgobj->fifo;
-
-       if ((irq_register & IR_RI) != 0) 
-               sja1000_irq_read_handler(chip, msgobj);
-       if ((irq_register & IR_TI) != 0) 
-               sja1000_irq_write_handler(chip, msgobj);
-       if ((irq_register & (IR_EI|IR_DOI)) != 0) { 
-               // Some error happened
-// FIXME: chip should be brought to usable state. Transmission cancelled if in progress.
-// Reset flag set to 0 if chip is already off the bus. Full state report
-               CANMSG("Error: status register: 0x%x irq_register: 0x%02x\n",
-                       can_read_reg(chip, SJASR), irq_register);
-               chip->msgobj[0]->ret=-1;
-               if (waitqueue_active(&fifo->writeq))
-                       wake_up_interruptible(&fifo->writeq);
-               if (waitqueue_active(&fifo->readq))
-                       wake_up_interruptible(&fifo->readq);
-       }
-
-       return;
-}
-
-void sja1000_irq_read_handler(struct chip_t *chip, struct msgobj_t *msgobj)
-{
-       int i=0, id=0;
-       struct canfifo_t *fifo=msgobj->fifo;
-
-       do {
-               id = can_read_reg(chip, SJARXID0) | (can_read_reg(chip, SJARXID1)<<8);
-               fifo->rx_writep->length = id & 0x0f;
-               fifo->rx_writep->flags = id&ID0_RTR ? MSG_RTR : 0;
-               fifo->rx_writep->timestamp = 0;
-               fifo->rx_writep->cob = 0;
-               fifo->rx_writep->id = id>>5;
-
-               for (i=0; i<fifo->rx_writep->length; i++)
-                       fifo->rx_writep->data[i]=can_read_reg(chip, SJARXDAT0 + i);
-
-               can_write_reg(chip, CMR_RRB, SJACMR);
-
-               fifo->rx_writep++;
-               if (fifo->rx_writep >= fifo->buf_rx_entry + MAX_BUF_LENGTH)
-                       fifo->rx_writep = fifo->buf_rx_entry;
-
-       } while(can_read_reg(chip, SJASR) & SR_RBS);
-
-       if (waitqueue_active(&fifo->readq))
-               wake_up_interruptible(&fifo->readq);
-}
-
-void sja1000_irq_write_handler(struct chip_t *chip, struct msgobj_t *msgobj)
-{
-       struct canfifo_t *fifo=msgobj->fifo;
-
-       fifo->tx_readp++;
-       if (fifo->tx_readp >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
-               fifo->tx_readp = fifo->buf_tx_entry;
-       if (fifo->tx_readp == fifo->tx_writep) { // Output buffer is empty
-               fifo->tx_in_progress = 0;
-               if (waitqueue_active(&fifo->writeq)) {
-                       msgobj->ret = 0;
-                       wake_up_interruptible(&fifo->writeq);
-               }
-               return;
-       }
-       if (chip->chipspecops->pre_write_config(chip, msgobj, fifo->tx_readp)) {
-               if (waitqueue_active(&fifo->writeq)) {
-                       msgobj->ret = -1;
-                       wake_up_interruptible(&fifo->writeq);
-                       return;
-               }
-       }
-       if (chip->chipspecops->send_msg(chip, msgobj, fifo->tx_readp)) {
-               if (waitqueue_active(&fifo->writeq)) {
-                       msgobj->ret = -1;
-                       wake_up_interruptible(&fifo->writeq);
-                       return;
-               }
-       }
-}
 
-void dummy_irq_handler(int irq, void *dev_id, struct pt_regs *regs) {
+irqreturn_t dummy_irq_handler(int irq, void *dev_id, struct pt_regs *regs) {
        CANMSG("dummy_irq_handler called irq %d \n", irq);
+       return IRQ_NONE;
 }
index 3be6f65..7405160 100644 (file)
@@ -1,8 +1,10 @@
 /* m437.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
-
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -62,15 +57,20 @@ static long base = 0L;
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/m437.c
  */
-int m437_request_io(unsigned long io_addr)
+int m437_request_io(struct candevice_t *candev)
 {
 
-       if ( !( base = (long) ioremap( io_addr, IO_RANGE ) ) ) {
-               CANMSG("Unable to access I/O memory at: 0x%lx\n", io_addr);
+       if (!request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
+               CANMSG("Unable to request IO-memory: 0x%lx\n",candev->io_addr);
+               return -ENODEV;
+       }
+
+       if ( !( base = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
+               CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
                return -ENODEV;
        
        }
-       DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + IO_RANGE - 1);
+       DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
        return 0;
 }
 
@@ -86,7 +86,7 @@ int m437_request_io(unsigned long io_addr)
  * Return Value: The function always returns zero
  * File: src/m437.c
  */
-int m437_release_io(unsigned long io_addr)
+int m437_release_io(struct candevice_t *candev)
 {
        unsigned i;
        
@@ -116,6 +116,8 @@ int m437_release_io(unsigned long io_addr)
        /* release I/O memory mapping */
        iounmap((void*)base);
 
+       release_mem_region(candev->io_addr,IO_RANGE);
+
        return 0;
 }
 
@@ -129,7 +131,7 @@ int m437_release_io(unsigned long io_addr)
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/m437.c
  */
-int m437_reset(int card)
+int m437_reset(struct candevice_t *candev)
 {
        return 0;
 }
@@ -152,13 +154,14 @@ int m437_reset(int card)
  * Return Value: The function always returns zero
  * File: src/m437.c
  */
-int m437_init_hw_data(int card
+int m437_init_hw_data(struct candevice_t *candev
 {
        DEBUGMSG("m437_init_hw_data()\n");
-       candevices_p[card]->res_addr=RESET_ADDR;
-       candevices_p[card]->nr_82527_chips=1;
-       candevices_p[card]->nr_sja1000_chips=0;
-       candevices_p[card]->flags &= ~PROGRAMMABLE_IRQ;
+       candev->res_addr=RESET_ADDR;
+       candev->nr_82527_chips=1;
+       candev->nr_sja1000_chips=0;
+        candev->nr_all_chips=1;
+       candev->flags &= ~PROGRAMMABLE_IRQ;
        /* The M437 has no programmable IRQ */
 
        return 0;
@@ -197,15 +200,15 @@ int m437_init_hw_data(int card)
  * Return Value: The function always returns zero
  * File: src/m437.c
  */
-int m437_init_chip_data(int card, int chipnr)
+int m437_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       candevices_p[card]->chip[chipnr]->chip_type=CHIP_TYPE;
-       candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->clock = 16000000;
-       candevices_p[card]->chip[chipnr]->int_cpu_reg = iCPU_DSC | iCPU_CEN;
-       candevices_p[card]->chip[chipnr]->int_clk_reg = 
+       candev->chip[chipnr]->chip_type=CHIP_TYPE;
+       candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+       candev->chip[chipnr]->clock = 16000000;
+       candev->chip[chipnr]->int_cpu_reg = iCPU_DSC | iCPU_CEN;
+       candev->chip[chipnr]->int_clk_reg = 
                iCLK_CD0 | iCLK_CD1 | iCLK_CD2 | iCLK_SL0 | iCLK_SL1;
-       candevices_p[card]->chip[chipnr]->int_bus_reg = iBUS_CBY;
+       candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
 
        return 0;
 }
@@ -227,10 +230,10 @@ int m437_init_chip_data(int card, int chipnr)
  * Return Value: The function always returns zero
  * File: src/m437.c
  */
-int m437_init_obj_data(int chipnr, int objnr)
+int m437_init_obj_data(struct chip_t *chip, int objnr)
 {
-       chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr+(objnr+1)*0x10;
-       chips_p[chipnr]->msgobj[objnr]->flags=0;
+       chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
+       chip->msgobj[objnr]->flags=0;
        
        return 0;
 }
@@ -247,7 +250,7 @@ int m437_init_obj_data(int chipnr, int objnr)
  * Return value: The function returns zero on success or %-ENODEV on failure
  * File: src/m437.c
  */
-int m437_program_irq(int card)
+int m437_program_irq(struct candevice_t *candev)
 {
        return 0;
 }
index f21e78f..d04c39c 100644 (file)
@@ -1,32 +1,30 @@
 /* main.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
  */
 
 #define EXPORT_SYMTAB
 
 #include <linux/autoconf.h>
-#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
-#define MODVERSIONS
-#endif
 
 #include <linux/module.h>
 
-#if defined (MODVERSIONS)
-#include <linux/modversions.h>
-#endif
-
 #include <linux/kernel.h>
 #include <linux/fs.h>
-#include <linux/wrapper.h>
 #include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/version.h>
 #include <linux/autoconf.h>
 #include <linux/interrupt.h>
 
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,50))
+#include <linux/wrapper.h>
+#endif
+
 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
 #include <asm/spinlock.h>
 #else
 #endif
 #endif
 
+/*#undef CONFIG_DEVFS_FS*/
+
 #ifdef CONFIG_DEVFS_FS
 #include <linux/miscdevice.h>
 #endif
 
 #include "../include/main.h"
 #include "../include/modparms.h"
+#include "../include/devcommon.h"
 #include "../include/setup.h"
 #include "../include/proc.h"
 #include "../include/open.h"
@@ -97,7 +98,6 @@ MODULE_DESCRIPTION("Universal Linux CAN-bus device driver");
 /* Global structures, used to describe the installed hardware. */
 struct canhardware_t canhardware;
 struct canhardware_t *hardware_p=&canhardware;
-struct candevice_t *candevices_p[MAX_HW_CARDS];
 struct chip_t *chips_p[MAX_TOT_CHIPS];
 struct msgobj_t *objects_p[MAX_TOT_MSGOBJS];
 #ifdef CONFIG_DEVFS_FS
@@ -142,6 +142,7 @@ EXPORT_SYMBOL(can_fops);
 int init_module(void)
 {
        int res=0,i=0;
+       struct candevice_t *candev;
 
        if (parse_mod_parms())
                return -EINVAL;
@@ -160,12 +161,14 @@ int init_module(void)
        }
 
        for (i=0; i<hardware_p->nr_boards; i++) {
-               if (candevices_p[i]->hwspecops->request_io(candevices_p[i]->io_addr)) 
-               goto memory_error;
+               candev=hardware_p->candevice[i];
+               if (candev->hwspecops->request_io(candev)) 
+                       goto memory_error;
        }
 
        for (i=0; i<hardware_p->nr_boards; i++) {
-               if (candevices_p[i]->hwspecops->reset(i)) 
+               candev=hardware_p->candevice[i];
+               if (candev->hwspecops->reset(candev)) 
                        goto reset_error;
        }
 
@@ -174,16 +177,8 @@ int init_module(void)
 
        i=0;
        while ( (chips_p[i] != NULL) && (i < MAX_TOT_CHIPS) ) {
-               if (!strcmp(chips_p[i]->chip_type,"i82527")) {
-                       if (request_irq(chips_p[i]->chip_irq,i82527_irq_handler,SA_SHIRQ,DEVICE_NAME,chips_p[i]))  
-                               goto interrupt_error;
-                       else
-                               DEBUGMSG("Registered interrupt %d\n",chips_p[i]->chip_irq);
-               }
-               if (!strcmp(chips_p[i]->chip_type,"sja1000p") ||  
-                               !strcmp(chips_p[i]->chip_type,"sja1000")) {
-                       if (request_irq(chips_p[i]->chip_irq,
-       chips_p[i]->chipspecops->irq_handler,SA_SHIRQ,DEVICE_NAME,chips_p[i]))
+               if (chips_p[i]->chipspecops->irq_handler) {
+                       if (request_irq(chips_p[i]->chip_irq,chips_p[i]->chipspecops->irq_handler,SA_SHIRQ,DEVICE_NAME,chips_p[i]))
                                goto interrupt_error;
                        else
                                DEBUGMSG("Registered interrupt %d\n",chips_p[i]->chip_irq);
@@ -192,8 +187,9 @@ int init_module(void)
        }
 
        for (i=0; i<hardware_p->nr_boards; i++) {
-               if (candevices_p[i]->flags & PROGRAMMABLE_IRQ)
-                       if (candevices_p[i]->hwspecops->program_irq(i))
+               candev=hardware_p->candevice[i];
+               if (candev->flags & PROGRAMMABLE_IRQ)
+                       if (candev->hwspecops->program_irq(candev))
                                goto interrupt_error;
        }
 
@@ -233,8 +229,10 @@ int init_module(void)
                goto memory_error;
 
        memory_error: ;
-               for (i=0; i<hardware_p->nr_boards; i++)
-                       candevices_p[i]->hwspecops->release_io(candevices_p[i]->io_addr);
+               for (i=0; i<hardware_p->nr_boards; i++) {
+                       candev=hardware_p->candevice[i];
+                       candev->hwspecops->release_io(candev);
+               }
                goto register_error;
 
        register_error: ;
@@ -250,6 +248,7 @@ int init_module(void)
 void cleanup_module(void)
 {
        int res=0,i=0;
+       struct candevice_t *candev;
 
 #ifdef CONFIG_PROC_FS
        if (can_delete_procdir())
@@ -268,8 +267,10 @@ void cleanup_module(void)
                i++;
        }
 
-       for (i=0; i<hardware_p->nr_boards; i++) 
-               candevices_p[i]->hwspecops->release_io(candevices_p[i]->io_addr);
+       for (i=0; i<hardware_p->nr_boards; i++){ 
+               candev=hardware_p->candevice[i];
+               candev->hwspecops->release_io(candev);
+       }
 
        if ( del_mem_list() ) 
                CANMSG("Error deallocating memory\n");
index cf4a325..96d66d5 100644 (file)
@@ -1,19 +1,14 @@
 /* mod_parms.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
 
 #include ".supported_cards.h"
 
@@ -170,24 +165,17 @@ int list_hw(void)
                printk(KERN_ERR "\n");
                DEBUGMSG("Hardware         : %s\n",hardware_p->candevice[i]->hwname);
                DEBUGMSG("IO address       : 0x%lx\n",hardware_p->candevice[i]->io_addr);
+               DEBUGMSG("Nr. all chips    : %d\n",hardware_p->candevice[i]->nr_all_chips);
                DEBUGMSG("Nr. of i82527    : %d\n",hardware_p->candevice[i]->nr_82527_chips);
                DEBUGMSG("Nr. of sja1000   : %d\n",hardware_p->candevice[i]->nr_sja1000_chips);
-               for (j=0; j<hardware_p->candevice[i]->nr_82527_chips+hardware_p->candevice[i]->nr_sja1000_chips; j++) {
+               for (j=0; j<hardware_p->candevice[i]->nr_all_chips; j++) {
                        DEBUGMSG("Chip%d type       : %s\n", j+1, hardware_p->candevice[i]->chip[j]->chip_type);
                        DEBUGMSG("Chip base        : 0x%lx\n",hardware_p->candevice[i]->chip[j]->chip_base_addr);
                        DEBUGMSG("Interrupt        : %d\n",hardware_p->candevice[i]->chip[j]->chip_irq);
 
 
-                       if (!strcmp(hardware_p->candevice[i]->chip[j]->chip_type,"i82527")) {
-                               for (k=0; k<15; k++)
-                                       DEBUGMSG("Obj%d: minor: %d base: 0x%lx\n",k,hardware_p->candevice[i]->chip[j]->msgobj[k]->minor,hardware_p->candevice[i]->chip[j]->msgobj[k]->obj_base_addr);
-                       }
-
-                       if (!strcmp(hardware_p->candevice[i]->chip[j]->chip_type,"sja1000")) {
-                               for (k=0; k<1; k++)
-                                       DEBUGMSG("Obj%d: minor: %d base: 0x%lx\n",k,hardware_p->candevice[i]->chip[j]->msgobj[k]->minor,hardware_p->candevice[i]->chip[j]->msgobj[k]->obj_base_addr);
-                       } 
-
+                       for (k=0; k<hardware_p->candevice[i]->chip[j]->max_objects; k++)
+                               DEBUGMSG("Obj%d: minor: %d base: 0x%lx\n",k,hardware_p->candevice[i]->chip[j]->msgobj[k]->minor,hardware_p->candevice[i]->chip[j]->msgobj[k]->obj_base_addr);
 
                }
                i++;
index 3fefebc..289a1ed 100644 (file)
@@ -1,18 +1,13 @@
 /* nsi.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
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -36,19 +31,17 @@ unsigned long nsican_base=0x0;
 /* The function template_request_io is used to reserve the io-memory. If your
  * hardware uses a dedicated memory range as hardware control registers you
  * will have to add the code to reserve this memory as well.
- * The reserved memory starts at io_addr, wich is the module parameter io.
+ * The reserved memory starts at candev->io_addr, wich is the module parameter io.
  */
-int nsi_request_io(unsigned long io_addr)
+int nsi_request_io(struct candevice_t *candev)
 {
 
-       if (check_region(io_addr,IO_RANGE)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr);
+       if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
                return -ENODEV;
-       }
-       else {
-               request_region(io_addr,IO_RANGE,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, 
-                        io_addr + IO_RANGE - 1);
+       } else {
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, 
+                        candev->io_addr + IO_RANGE - 1);
        }
        return 0;
 }
@@ -56,10 +49,10 @@ int nsi_request_io(unsigned long io_addr)
 /* The function template_release_io is used to free the previously reserved 
  * io-memory. In case you reserved more memory, don't forget to free it here.
  */
-int nsi_release_io(unsigned long io_addr)
+int nsi_release_io(struct candevice_t *candev)
 {
 
-       release_region(io_addr,IO_RANGE);
+       can_release_io_region(candev->io_addr,IO_RANGE);
 
        return 0;
 }
@@ -68,15 +61,15 @@ int nsi_release_io(unsigned long io_addr)
  * hardware specific so I haven't included example code. Don't forget to check
  * the reset status of the chip before returning.
  */
-int nsi_reset(int card)
+int nsi_reset(struct candevice_t *candev)
 {
     int i; 
 
     DEBUGMSG("Resetting nsi hardware ...\n");
     /* we don't use template_write_register because we don't use the two first
        register of the card but the third in order to make a hard reset */
-    outb (1, nsican_base + candevices_p[card]->res_addr);
-    outb (0, nsican_base + candevices_p[card]->res_addr);
+    outb (1, nsican_base + candev->res_addr);
+    outb (0, nsican_base + candev->res_addr);
     for (i = 1; i < 1000; i++)
        udelay (1000);
     
@@ -110,12 +103,13 @@ int nsi_reset(int card)
 #define NR_82527 1
 #define NR_SJA1000 0
 
-int nsi_init_hw_data(int card
+int nsi_init_hw_data(struct candevice_t *candev
      {
-       candevices_p[card]->res_addr=RESET_ADDR;
-       candevices_p[card]->nr_82527_chips=1;
-       candevices_p[card]->nr_sja1000_chips=0;
-       candevices_p[card]->flags |= PROGRAMMABLE_IRQ;
+       candev->res_addr=RESET_ADDR;
+       candev->nr_82527_chips=1;
+       candev->nr_sja1000_chips=0;
+        candev->nr_all_chips=1;
+       candev->flags |= PROGRAMMABLE_IRQ;
 
        return 0;
 }
@@ -125,23 +119,23 @@ int nsi_init_hw_data(int card)
  * CHIP_TYPE represents the type of CAN chip. CHIP_TYPE can be "i82527" or
  * "sja1000".
  * The chip_base_addr entry represents the start of the 'official' memory map
- * of the installed chip. It's likely that this is the same as the io_addr
+ * of the installed chip. It's likely that this is the same as the candev->io_addr
  * argument supplied at module loading time.
  * The clock argument holds the chip clock value in Hz.
  */
 #define CHIP_TYPE "i82527"
 
-int nsi_init_chip_data(int card, int chipnr)
+int nsi_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       candevices_p[card]->chip[chipnr]->chip_type=CHIP_TYPE;
-       candevices_p[card]->chip[chipnr]->chip_base_addr=
-           candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->clock = 16000000;
-       nsican_irq=candevices_p[card]->chip[chipnr]->chip_irq;  
-        nsican_base=candevices_p[card]->chip[chipnr]->chip_base_addr;
-       candevices_p[card]->chip[chipnr]->int_cpu_reg = iCPU_DSC;
-       candevices_p[card]->chip[chipnr]->int_clk_reg = iCLK_SL1;
-       candevices_p[card]->chip[chipnr]->int_bus_reg = iBUS_CBY;
+       candev->chip[chipnr]->chip_type=CHIP_TYPE;
+       candev->chip[chipnr]->chip_base_addr=
+           candev->io_addr;
+       candev->chip[chipnr]->clock = 16000000;
+       nsican_irq=candev->chip[chipnr]->chip_irq;      
+        nsican_base=candev->chip[chipnr]->chip_base_addr;
+       candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
+       candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
+       candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
 
        return 0;
 }
@@ -156,12 +150,12 @@ int nsi_init_chip_data(int card, int chipnr)
  * base address.
  * Unless the hardware uses a segmented memory map, flags can be set zero.
  */
-int nsi_init_obj_data(int chipnr, int objnr)
+int nsi_init_obj_data(struct chip_t *chip, int objnr)
 {
 
-       chips_p[chipnr]->msgobj[objnr]->obj_base_addr=
-           chips_p[chipnr]->chip_base_addr+(objnr+1)*0x10;
-       chips_p[chipnr]->msgobj[objnr]->flags=0;
+       chip->msgobj[objnr]->obj_base_addr=
+           chip->chip_base_addr+(objnr+1)*0x10;
+       chip->msgobj[objnr]->flags=0;
        
        return 0;
 }
@@ -172,7 +166,7 @@ int nsi_init_obj_data(int chipnr, int objnr)
  * function unedited. Again this function is hardware specific so there's no
  * example code.
  */
-int nsi_program_irq(int card)
+int nsi_program_irq(struct candevice_t *candev)
 {
        return 0;
 }
index f9ff108..e980f16 100644 (file)
@@ -1,30 +1,24 @@
 /* open.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
  */
 
 #define __NO_VERSION__
 #include <linux/module.h> 
 
 #include <linux/autoconf.h>
-#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
-#define MODVERSIONS
-#endif
-
-#if defined (MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 
 #include <linux/fs.h>
 #include <linux/version.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
 #include <linux/malloc.h>
 #else
 #include <linux/slab.h>
 #endif
-#include <linux/version.h>
 
 #include "../include/main.h"
 #include "../include/open.h"
@@ -35,7 +29,8 @@ int can_open(struct inode *inode, struct file *file)
 {
        struct msgobj_t *obj;
        struct chip_t *chip;
-       struct canfifo_t *fifo;
+       struct canuser_t *canuser;
+       struct canque_ends_t *qends;
 
        if ( ((obj=objects_p[MINOR_NR]) == NULL) || 
                        ((chip=objects_p[MINOR_NR]->hostchip) == NULL) ) {
@@ -43,64 +38,62 @@ int can_open(struct inode *inode, struct file *file)
                return -ENODEV;
        }
 
-       if (objects_p[MINOR_NR]->flags & OPENED) {
-               CANMSG("Sorry, only single open per device file.\n");
-               return -EBUSY;
-       }
-       else
-               objects_p[MINOR_NR]->flags |= OPENED;
+       atomic_inc(&obj->obj_used);
+       DEBUGMSG("Device %d opened %d times.\n", MINOR_NR, atomic_read(&obj->obj_used));
+       obj->flags |= OBJ_OPENED;
 
-       if (chip->flags & CONFIGURED) 
+       if (chip->flags & CHIP_CONFIGURED) 
                DEBUGMSG("Device is already configured.\n");
        else {
                if (chip->chipspecops->chip_config(chip))
                        CANMSG("Error configuring chip.\n");
                else
-                       chip->flags |= CONFIGURED; 
+                       chip->flags |= CHIP_CONFIGURED; 
+
+               if (chip->chipspecops->pre_read_config(chip,obj)<0)
+                       CANMSG("Error initializing chip for receiving\n");
+
+               /* chip->flags |= OBJ_BUFFERS_ALLOCATED; */
+               
        } /* End of chip configuration */
 
-       /* Allocate output buffer memory for the opened device */
-       fifo = objects_p[MINOR_NR]->fifo;
-       fifo->buf_tx_entry=(struct canmsg_t *)kmalloc(MAX_BUF_LENGTH * sizeof(struct canmsg_t), GFP_KERNEL);
-       if (fifo->buf_tx_entry == NULL)
-               return -ENOMEM;
-       else
-               if ( add_mem_to_list(fifo->buf_tx_entry) )
-                       return -ENOMEM;
-       /* Allocate input buffer memory for the opened device */
-       fifo->buf_rx_entry=(struct canmsg_t *)kmalloc(MAX_BUF_LENGTH * sizeof(struct canmsg_t), GFP_KERNEL);
-       if (fifo->buf_rx_entry == NULL)
-               return -ENOMEM;
-       else
-               if ( add_mem_to_list(fifo->buf_rx_entry) )
-                       return -ENOMEM;
-
-       /* In- and output buffer initialization */
-       fifo->tx_readp = fifo->buf_tx_entry;
-       fifo->tx_writep = fifo->buf_tx_entry;
-       fifo->rx_readp = fifo->buf_rx_entry;
-       fifo->rx_writep = fifo->buf_rx_entry;
-       fifo->rx_size = MAX_BUF_LENGTH * sizeof(struct canmsg_t);
-       fifo->tx_size = fifo->rx_size;
-
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
-       init_waitqueue(&fifo->readq);
-       init_waitqueue(&fifo->writeq);
-#else
-       init_waitqueue_head(&fifo->readq);
-       init_waitqueue_head(&fifo->writeq);
-#endif
+       canuser = (struct canuser_t *)kmalloc(sizeof(struct canuser_t), GFP_KERNEL);
+       if(canuser == NULL) goto no_canuser;
+       canuser->file = file;
+       canuser->msgobj = obj;
+       canuser->magic = CAN_USER_MAGIC;
+       file->private_data = canuser;
 
-       fifo->rx_in_progress = 0;
-       fifo->tx_in_progress = 0;
+       qends = (struct canque_ends_t *)kmalloc(sizeof(struct canque_ends_t), GFP_KERNEL);
+       if(qends == NULL) goto no_qends;
+       canqueue_ends_init_kern(qends);
+       canuser->qends = qends;
+       
+       list_add(&canuser->peers, &obj->obj_users);
 
-       chip->flags |= BUFFERS_ALLOCATED;
+       if(canqueue_connect_edge(canque_new_edge_kern(MAX_BUF_LENGTH),
+               canuser->qends, obj->qends)<0) goto no_qedge;
+
+       if(canqueue_connect_edge(canuser->rx_edge0=canque_new_edge_kern(MAX_BUF_LENGTH),
+               obj->qends, canuser->qends)<0) goto no_qedge;
 
-       if (chip->chipspecops->pre_read_config(chip,obj)<0)
-               CANMSG("Error initializing chip for receiving\n");
-               
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,50))
        MOD_INC_USE_COUNT;
 #endif 
+
        return 0;
+       
+    no_qedge:
+       list_del(&canuser->peers);
+       canqueue_ends_done_kern(qends, 1);
+       canuser->qends = NULL;
+       kfree(qends);
+       obj->qends = NULL;
+
+    no_qends:
+       kfree(canuser);
+
+    no_canuser:
+       atomic_dec(&obj->obj_used);
+       return -ENOMEM;
 }
index bf64ff6..0490fe6 100644 (file)
@@ -1,18 +1,13 @@
 /* pc-i03.c
  * Linux CAN-bus device driver.
  * Written by Arnaud Westenberg email:arnaud@wnadoo.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
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -50,15 +45,13 @@ unsigned int pci03_base_addr;
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/pc-i03.c
  */
-int pci03_request_io(unsigned long io_addr)
+int pci03_request_io(struct candevice_t *candev)
 {
-       if (check_region(io_addr,IO_RANGE)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr);
+       if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
                return -ENODEV;
-       }
-       else {
-               request_region(io_addr,IO_RANGE,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + IO_RANGE - 1);
+       } else {
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
        }
        return 0;
 }
@@ -75,9 +68,9 @@ int pci03_request_io(unsigned long io_addr)
  * Return Value: The function always returns zero
  * File: src/pc-i03.c
  */
-int pci03_release_io(unsigned long io_addr)
+int pci03_release_io(struct candevice_t *candev)
 {
-       release_region(io_addr,IO_RANGE);
+       can_release_io_region(candev->io_addr,IO_RANGE);
 
        return 0;
 }
@@ -92,7 +85,7 @@ int pci03_release_io(unsigned long io_addr)
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/pc-i03.c
  */
-int pci03_reset(int card)
+int pci03_reset(struct candevice_t *candev)
 {
        int i=0;
 
@@ -139,13 +132,12 @@ int pci03_reset(int card)
  * Return Value: The function always returns zero
  * File: src/pc-i03.c
  */
-int pci03_init_hw_data(int card
+int pci03_init_hw_data(struct candevice_t *candev
 {
-       candevices_p[card]->res_addr=RESET_ADDR;
-       candevices_p[card]->nr_82527_chips=NR_82527;
-       candevices_p[card]->nr_sja1000_chips=NR_SJA1000;
-       candevices_p[card]->flags |= ~PROGRAMMABLE_IRQ;
-
+       candev->res_addr=RESET_ADDR;
+       candev->nr_82527_chips=NR_82527;
+        candev->nr_sja1000_chips=NR_SJA1000;
+       candev->nr_all_chips=NR_82527+NR_SJA1000;
        return 0;
 }
 
@@ -179,14 +171,14 @@ int pci03_init_hw_data(int card)
  * Return Value: The function always returns zero
  * File: src/pc-i03.c
  */
-int pci03_init_chip_data(int card, int chipnr)
+int pci03_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       pci03_base_addr = candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->chip_type=CHIP_TYPE;
-       candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->clock = 16000000;
-       candevices_p[card]->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
-       candevices_p[card]->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL | 
+       pci03_base_addr = candev->io_addr;
+       candev->chip[chipnr]->chip_type=CHIP_TYPE;
+       candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+       candev->chip[chipnr]->clock = 16000000;
+       candev->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
+       candev->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL | 
                                                        OCR_TX0_HL | OCR_TX1_LZ;
 
        return 0;
@@ -209,10 +201,10 @@ int pci03_init_chip_data(int card, int chipnr)
  * Return Value: The function always returns zero
  * File: src/pc-i03.c
  */
-int pci03_init_obj_data(int chipnr, int objnr)
+int pci03_init_obj_data(struct chip_t *chip, int objnr)
 {
-       chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr;
-       chips_p[chipnr]->msgobj[objnr]->flags=0;
+       chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
+       chip->msgobj[objnr]->flags=0;
        
        return 0;
 }
@@ -229,7 +221,7 @@ int pci03_init_obj_data(int chipnr, int objnr)
  * Return value: The function returns zero on success or %-ENODEV on failure
  * File: src/pc-i03.c
  */
-int pci03_program_irq(int card)
+int pci03_program_irq(struct candevice_t *candev)
 {
        return 0;
 }
index bf5a8a8..06e9e05 100644 (file)
 /* pccan.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
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <asm/irq.h>
 #include <asm/errno.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 
 #include "../include/main.h"
 #include "../include/pccan.h"
 #include "../include/i82527.h"
 #include "../include/sja1000.h"
 
-int pccanf_request_io(unsigned long io_addr)
+int pccanf_request_io(struct candevice_t *candev)
 {
-       if (check_region(io_addr+0x4000,0x20)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x4000);
+       if (!can_request_io_region(candev->io_addr+0x4000,0x20,DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr+0x4000);
                return -ENODEV;
        }
-       else if (check_region(io_addr+0x6000,0x04)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x6000);
+       else if (!can_request_io_region(candev->io_addr+0x6000,0x04,DEVICE_NAME)) {
+               can_release_io_region(candev->io_addr+0x4000,0x20);
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr+0x6000);
                return -ENODEV;
        }
        else {
-               request_region(io_addr+0x4000,0x20,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x4000, io_addr+0x4000+0x20-1);
-               request_region(io_addr+0x6000,0x04,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x6000, io_addr+0x6000+0x04-1);
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr+0x4000, candev->io_addr+0x4000+0x20-1);
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr+0x6000, candev->io_addr+0x6000+0x04-1);
        }
        return 0;
 }
 
-int pccand_request_io(unsigned long io_addr)
+int pccand_request_io(struct candevice_t *candev)
 {
-       if (pccanf_request_io(io_addr))
+       if (pccanf_request_io(candev))
                return -ENODEV;
 
-       if (check_region(io_addr+0x5000,0x20)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x5000);
+       if (!can_request_io_region(candev->io_addr+0x5000,0x20,DEVICE_NAME)) {
+               pccanf_release_io(candev);
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr+0x5000);
                return -ENODEV;
        }
        else {
-               request_region(io_addr+0x5000,0x20,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x5000, io_addr+0x5000+0x20-1);
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr+0x5000, candev->io_addr+0x5000+0x20-1);
        }
        return 0;
 }
 
-int pccanq_request_io(unsigned long io_addr)
+int pccanq_request_io(struct candevice_t *candev)
 {
-       if (pccand_request_io(io_addr))
+       unsigned long io_addr;
+       int i;
+       
+       if (pccand_request_io(candev))
                return -ENODEV;
 
-       if (check_region(io_addr+0x2000,0x40)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x2000);
-               return -ENODEV;
-       }
-       else if (check_region(io_addr+0x2400,0x40)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x2400);
-               return -ENODEV;
-       }
-       else if (check_region(io_addr+0x2800,0x40)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x2800);
-               return -ENODEV;
-       }
-       else if (check_region(io_addr+0x2C00,0x40)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x2C00);
-               return -ENODEV;
-       }
-       else if (check_region(io_addr+0x3000,0x40)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x3000);
-               return -ENODEV;
-       }
-       else if (check_region(io_addr+0x3400,0x40)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x3400);
-               return -ENODEV;
-       }
-       else if (check_region(io_addr+0x3800,0x40)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x3800);
-               return -ENODEV;
-       }
-       else if (check_region(io_addr+0x3C00,0x40)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x3C00);
-               return -ENODEV;
-       }
-       else {
-               request_region(io_addr+0x2000,0x40,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x2000, io_addr+0x2000+0x40-1);
-               request_region(io_addr+0x2400,0x40,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x2400, io_addr+0x2400+0x40-1);
-               request_region(io_addr+0x2800,0x40,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x2800, io_addr+0x2800+0x40-1);
-               request_region(io_addr+0x2C00,0x40,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x2C00, io_addr+0x2C00+0x40-1);
-               request_region(io_addr+0x3000,0x40,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x3000, io_addr+0x3000+0x40-1);
-               request_region(io_addr+0x3400,0x40,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x3400, io_addr+0x3400+0x40-1);
-               request_region(io_addr+0x3800,0x40,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x3800, io_addr+0x3800+0x40-1);
-               request_region(io_addr+0x3C00,0x40,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x3C00, io_addr+0x3C00+0x40-1);
+       for(i=0, io_addr=candev->io_addr+0x2000; i<8; i++, io_addr+=0x400) {
+               if (!can_request_io_region(io_addr,0x40,DEVICE_NAME)) {
+                       CANMSG("Unable to open port: 0x%lx\n",io_addr);
+                       while(i--){
+                               io_addr-=0x400;
+                               can_release_io_region(io_addr,0x40);
+                       }
+                       pccand_release_io(candev);
+                       return -ENODEV;
+               }
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr+0x40-1);
        }
-
        return 0;
 }
 
-int pccanf_release_io(unsigned long io_addr)
+int pccanf_release_io(struct candevice_t *candev)
 {
-       release_region(io_addr+0x4000,0x20);
-       release_region(io_addr+0x6000,0x04);
+       can_release_io_region(candev->io_addr+0x4000,0x20);
+       can_release_io_region(candev->io_addr+0x6000,0x04);
 
        return 0;
 }
 
-int pccand_release_io(unsigned long io_addr)
+int pccand_release_io(struct candevice_t *candev)
 {
-       pccanf_release_io(io_addr);
-       release_region(io_addr+0x5000,0x20);
+       pccanf_release_io(candev);
+       can_release_io_region(candev->io_addr+0x5000,0x20);
 
        return 0;
 }
 
-int pccanq_release_io(unsigned long io_addr)
+int pccanq_release_io(struct candevice_t *candev)
 {
-       pccand_release_io(io_addr);
-       release_region(io_addr+0x2000,0x40);
-       release_region(io_addr+0x2400,0x40);
-       release_region(io_addr+0x2800,0x40);
-       release_region(io_addr+0x2C00,0x40);
-       release_region(io_addr+0x3000,0x40);
-       release_region(io_addr+0x3400,0x40);
-       release_region(io_addr+0x3800,0x40);
-       release_region(io_addr+0x3C00,0x40);
+       unsigned long io_addr;
+       int i;
+
+       pccand_release_io(candev);
+
+       for(i=0, io_addr=candev->io_addr+0x2000; i<8; i++, io_addr+=0x400) {
+               can_release_io_region(io_addr,0x40);
+       }
 
        return 0;
 }
 
-int pccanf_reset(int card)
+int pccanf_reset(struct candevice_t *candev)
 {
        int i=0;
 
        DEBUGMSG("Resetting pccanf/s hardware ...\n");
        while (i < 1000000) {
                i++;
-               outb(0x00,candevices_p[card]->res_addr);
+               outb(0x00,candev->res_addr);
        }
-       outb(0x01,candevices_p[card]->res_addr);
-       outb(0x00,candevices_p[card]->chip[0]->chip_base_addr+SJACR);
+       outb(0x01,candev->res_addr);
+       outb(0x00,candev->chip[0]->chip_base_addr+SJACR);
 
        /* Check hardware reset status */
        i=0;
-       while ( (inb(candevices_p[card]->chip[0]->chip_base_addr+SJACR) & CR_RR)
+       while ( (inb(candev->chip[0]->chip_base_addr+SJACR) & CR_RR)
                                                                 && (i<=15) ) {
                udelay(20000);
                i++;
@@ -180,24 +137,24 @@ int pccanf_reset(int card)
        return 0;
 }
 
-int pccand_reset(int card)
+int pccand_reset(struct candevice_t *candev)
 {
        int i=0,chip_nr=0;
 
        DEBUGMSG("Resetting pccan-d hardware ...\n");
        while (i < 1000000) {
                i++;
-               outb(0x00,candevices_p[card]->res_addr);
+               outb(0x00,candev->res_addr);
        }
-       outb(0x01,candevices_p[card]->res_addr);
-       outb(0x00,candevices_p[card]->chip[0]->chip_base_addr+SJACR);
-       outb(0x00,candevices_p[card]->chip[1]->chip_base_addr+SJACR);
+       outb(0x01,candev->res_addr);
+       outb(0x00,candev->chip[0]->chip_base_addr+SJACR);
+       outb(0x00,candev->chip[1]->chip_base_addr+SJACR);
 
        /* Check hardware reset status */
        i=0;
        for (chip_nr=0; chip_nr<2; chip_nr++) {
                i=0;
-               while ( (inb(candevices_p[card]->chip[chip_nr]->chip_base_addr +
+               while ( (inb(candev->chip[chip_nr]->chip_base_addr +
                                                SJACR) & CR_RR) && (i<=15) ) {
                        udelay(20000);
                        i++;
@@ -213,27 +170,27 @@ int pccand_reset(int card)
        return 0;
 }
 
-int pccanq_reset(int card)
+int pccanq_reset(struct candevice_t *candev)
 {
        int i=0,chip_nr=0;
 
        for (i=0; i<4; i++)
-               disable_irq(candevices_p[card]->chip[i]->chip_irq);
+               disable_irq(candev->chip[i]->chip_irq);
 
        DEBUGMSG("Resetting pccan-q hardware ...\n");
        while (i < 100000) {
                i++;
-               outb(0x00,candevices_p[card]->res_addr);
+               outb(0x00,candev->res_addr);
        }
-       outb_p(0x01,candevices_p[card]->res_addr);
+       outb_p(0x01,candev->res_addr);
                
-       outb(0x00,candevices_p[card]->chip[2]->chip_base_addr+SJACR);
-       outb(0x00,candevices_p[card]->chip[3]->chip_base_addr+SJACR);
+       outb(0x00,candev->chip[2]->chip_base_addr+SJACR);
+       outb(0x00,candev->chip[3]->chip_base_addr+SJACR);
 
        /* Check hardware reset status */
        for (chip_nr=0; chip_nr<2; chip_nr++) {
                i=0;
-               while( (inb(candevices_p[card]->chip[chip_nr]->chip_base_addr +
+               while( (inb(candev->chip[chip_nr]->chip_base_addr +
                                                iCPU) & iCPU_RST) && (i<=15) ) {
                        udelay(20000);
                        i++;
@@ -248,7 +205,7 @@ int pccanq_reset(int card)
        }
        for (chip_nr=2; chip_nr<4; chip_nr++) {
                i=0;
-               while( (inb(candevices_p[card]->chip[chip_nr]->chip_base_addr +
+               while( (inb(candev->chip[chip_nr]->chip_base_addr +
                                                SJACR) & CR_RR) && (i<=15) ) {
                        udelay(20000);
                        i++;
@@ -263,90 +220,93 @@ int pccanq_reset(int card)
        }
 
        for (i=0; i<4; i++)
-               enable_irq(candevices_p[card]->chip[i]->chip_irq);
+               enable_irq(candev->chip[i]->chip_irq);
 
        return 0;
 }      
 
-int pccan_init_hw_data(int card)
+int pccan_init_hw_data(struct candevice_t *candev)
 {
-       candevices_p[card]->res_addr=candevices_p[card]->io_addr+0x6001;
-       candevices_p[card]->flags |= PROGRAMMABLE_IRQ;
+       candev->res_addr=candev->io_addr+0x6001;
+       candev->flags |= PROGRAMMABLE_IRQ;
 
-       if (!strcmp(candevices_p[card]->hwname,"pccan-q")) {
-               candevices_p[card]->nr_82527_chips=2;
-               candevices_p[card]->nr_sja1000_chips=2;
+       if (!strcmp(candev->hwname,"pccan-q")) {
+               candev->nr_82527_chips=2;
+               candev->nr_sja1000_chips=2;
+               candev->nr_all_chips=4;
        }
-       if (!strcmp(candevices_p[card]->hwname,"pccan-f") |
-           !strcmp(candevices_p[card]->hwname,"pccan-s")) {
-               candevices_p[card]->nr_82527_chips=0;
-               candevices_p[card]->nr_sja1000_chips=1;
+       if (!strcmp(candev->hwname,"pccan-f") |
+           !strcmp(candev->hwname,"pccan-s")) {
+               candev->nr_82527_chips=0;
+               candev->nr_sja1000_chips=1;
+               candev->nr_all_chips=1;
        }
-       if (!strcmp(candevices_p[card]->hwname,"pccan-d")) {
-               candevices_p[card]->nr_82527_chips=0;
-               candevices_p[card]->nr_sja1000_chips=2;
+       if (!strcmp(candev->hwname,"pccan-d")) {
+               candev->nr_82527_chips=0;
+               candev->nr_sja1000_chips=2;
+               candev->nr_all_chips=2;
        }
 
        return 0;
 }
 
-int pccan_init_chip_data(int card, int chipnr)
+int pccan_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       if (!strcmp(candevices_p[card]->hwname,"pccan-q")) {
+       if (!strcmp(candev->hwname,"pccan-q")) {
                if (chipnr<2) {
-                       candevices_p[card]->chip[chipnr]->chip_type="i82527";
-                       candevices_p[card]->chip[chipnr]->flags = SEGMENTED;
-                       candevices_p[card]->chip[chipnr]->int_cpu_reg=iCPU_DSC;
-                       candevices_p[card]->chip[chipnr]->int_clk_reg=iCLK_SL1;
-                       candevices_p[card]->chip[chipnr]->int_bus_reg=iBUS_CBY;
-                       candevices_p[card]->chip[chipnr]->sja_cdr_reg = 0;
-                       candevices_p[card]->chip[chipnr]->sja_ocr_reg = 0;      
+                       candev->chip[chipnr]->chip_type="i82527";
+                       candev->chip[chipnr]->flags = CHIP_SEGMENTED;
+                       candev->chip[chipnr]->int_cpu_reg=iCPU_DSC;
+                       candev->chip[chipnr]->int_clk_reg=iCLK_SL1;
+                       candev->chip[chipnr]->int_bus_reg=iBUS_CBY;
+                       candev->chip[chipnr]->sja_cdr_reg = 0;
+                       candev->chip[chipnr]->sja_ocr_reg = 0;  
                }
                else{
-                       candevices_p[card]->chip[chipnr]->chip_type="sja1000";
-                       candevices_p[card]->chip[chipnr]->flags = 0;
-                       candevices_p[card]->chip[chipnr]->int_cpu_reg = 0;
-                       candevices_p[card]->chip[chipnr]->int_clk_reg = 0;
-                       candevices_p[card]->chip[chipnr]->int_bus_reg = 0;
-                       candevices_p[card]->chip[chipnr]->sja_cdr_reg =
+                       candev->chip[chipnr]->chip_type="sja1000";
+                       candev->chip[chipnr]->flags = 0;
+                       candev->chip[chipnr]->int_cpu_reg = 0;
+                       candev->chip[chipnr]->int_clk_reg = 0;
+                       candev->chip[chipnr]->int_bus_reg = 0;
+                       candev->chip[chipnr]->sja_cdr_reg =
                                                                CDR_CLK_OFF;
-                       candevices_p[card]->chip[chipnr]->sja_ocr_reg = 
+                       candev->chip[chipnr]->sja_ocr_reg = 
                                                OCR_MODE_NORMAL | OCR_TX0_LH;   
                }
-               candevices_p[card]->chip[chipnr]->chip_base_addr=0x1000*chipnr+0x2000+candevices_p[card]->io_addr;
+               candev->chip[chipnr]->chip_base_addr=0x1000*chipnr+0x2000+candev->io_addr;
        }
        else {
-               candevices_p[card]->chip[chipnr]->chip_type="sja1000";
-               candevices_p[card]->chip[chipnr]->chip_base_addr=0x1000*chipnr+0x4000+candevices_p[card]->io_addr;
-               candevices_p[card]->chip[chipnr]->flags = 0;
-               candevices_p[card]->chip[chipnr]->int_cpu_reg = 0;
-               candevices_p[card]->chip[chipnr]->int_clk_reg = 0;
-               candevices_p[card]->chip[chipnr]->int_bus_reg = 0;
-               candevices_p[card]->chip[chipnr]->sja_cdr_reg = CDR_CLK_OFF;
-               candevices_p[card]->chip[chipnr]->sja_ocr_reg = 
+               candev->chip[chipnr]->chip_type="sja1000";
+               candev->chip[chipnr]->chip_base_addr=0x1000*chipnr+0x4000+candev->io_addr;
+               candev->chip[chipnr]->flags = 0;
+               candev->chip[chipnr]->int_cpu_reg = 0;
+               candev->chip[chipnr]->int_clk_reg = 0;
+               candev->chip[chipnr]->int_bus_reg = 0;
+               candev->chip[chipnr]->sja_cdr_reg = CDR_CLK_OFF;
+               candev->chip[chipnr]->sja_ocr_reg = 
                                                OCR_MODE_NORMAL | OCR_TX0_LH;   
        }
 
-       candevices_p[card]->chip[chipnr]->clock = 16000000;
+       candev->chip[chipnr]->clock = 16000000;
 
        return 0;
 }      
 
-int pccan_init_obj_data(int chipnr, int objnr)
+int pccan_init_obj_data(struct chip_t *chip, int objnr)
 {
-       if (!strcmp(chips_p[chipnr]->chip_type,"sja1000")) {
-               chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr;
-               chips_p[chipnr]->msgobj[objnr]->flags=0;
+       if (!strcmp(chip->chip_type,"sja1000")) {
+               chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
+               chip->msgobj[objnr]->flags=0;
        }
-       else {
-               chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr+(objnr+1)*0x10+(int)((objnr+1)/4)*0x3c0;
-               chips_p[chipnr]->msgobj[objnr]->flags=0;
+       else {  /* The spacing for this card is 0x3c0 */
+               chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10+(int)((objnr+1)/4)*0x3c0;
+               chip->msgobj[objnr]->flags=0;
        }
 
        return 0;
 }
 
-int pccan_program_irq(int card)
+int pccan_program_irq(struct candevice_t *candev)
 {
        #define IRQ9 0x01
        #define IRQ3 0x02
@@ -356,7 +316,7 @@ int pccan_program_irq(int card)
        int i;
 
        for (i=0; i<4; i++) {
-               switch (candevices_p[card]->chip[i]->chip_irq) {
+               switch (candev->chip[i]->chip_irq) {
                        case 0: {
                                break;
                        }
@@ -378,9 +338,9 @@ int pccan_program_irq(int card)
                        }
                }
        }
-       outb(irq_reg_value,0x6000+candevices_p[card]->io_addr);
+       outb(irq_reg_value,0x6000+candev->io_addr);
        DEBUGMSG("Configured pccan hardware interrupts\n");
-       outb(0x80,0x6000+candevices_p[card]->io_addr+0x02);
+       outb(0x80,0x6000+candev->io_addr+0x02);
        DEBUGMSG("Selected pccan on-board 16 MHz oscillator\n");
 
        return 0;
index e7b5b22..290a44a 100644 (file)
@@ -1,8 +1,10 @@
 /* pcccan.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
  */ 
 
 /* This file contains the low level functions for the pcccan-1 card from Gespac.
  */
 
 #include <linux/autoconf.h>
-#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
-#define MODVERSIONS
-#endif
-
-#if defined (MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -66,15 +61,13 @@ unsigned long pcccan_base=0x0;
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/pcccan.c
  */
-int pcccan_request_io(unsigned long io_addr)
+int pcccan_request_io(struct candevice_t *candev)
 {
-       if (check_region(io_addr,IO_RANGE)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr);
+       if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
                return -ENODEV;
-       }
-       else {
-               request_region(io_addr,IO_RANGE,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + IO_RANGE - 1);
+       } else {
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
        }
        return 0;
 }
@@ -91,9 +84,9 @@ int pcccan_request_io(unsigned long io_addr)
  * Return Value: The function always returns zero
  * File: src/pcccan.c
  */
-int pcccan_release_io(unsigned long io_addr)
+int pcccan_release_io(struct candevice_t *candev)
 {
-       release_region(io_addr,IO_RANGE);
+       can_release_io_region(candev->io_addr,IO_RANGE);
 
        return 0;
 }
@@ -108,20 +101,20 @@ int pcccan_release_io(unsigned long io_addr)
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/pcccan.c
  */
-int pcccan_reset(int card)
+int pcccan_reset(struct candevice_t *candev)
 {
        int i=0;
 
        DEBUGMSG("Resetting pcccan-1 hardware ...\n");
        while (i < 1000000) {
                i++;
-               outb(0x0,candevices_p[card]->res_addr);
+               outb(0x0,candev->res_addr);
        }
 
        /* Check hardware reset status */
        i=0;
-       outb(iCPU,candevices_p[card]->io_addr+0x1);
-       while ( (inb(candevices_p[card]->io_addr+0x2)&0x80) && (i<=15) ) {
+       outb(iCPU,candev->io_addr+0x1);
+       while ( (inb(candev->io_addr+0x2)&0x80) && (i<=15) ) {
                udelay(20000);
                i++;
        }
@@ -153,12 +146,13 @@ int pcccan_reset(int card)
  * Return Value: The function always returns zero
  * File: src/pcccan.c
  */
-int pcccan_init_hw_data(int card
+int pcccan_init_hw_data(struct candevice_t *candev
 {
-       candevices_p[card]->res_addr=candevices_p[card]->io_addr;
-       candevices_p[card]->nr_82527_chips=NR_82527;
-       candevices_p[card]->nr_sja1000_chips=NR_SJA1000;
-       candevices_p[card]->flags |= ~PROGRAMMABLE_IRQ;
+       candev->res_addr=candev->io_addr;
+       candev->nr_82527_chips=NR_82527;
+       candev->nr_sja1000_chips=NR_SJA1000;
+        candev->nr_all_chips=NR_82527+NR_SJA1000;
+       candev->flags &= ~PROGRAMMABLE_IRQ;
 
        return 0;
 }
@@ -196,18 +190,18 @@ int pcccan_init_hw_data(int card)
  * Return Value: The function always returns zero
  * File: src/pcccan.c
  */
-int pcccan_init_chip_data(int card, int chipnr)
+int pcccan_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       candevices_p[card]->chip[chipnr]->chip_type=CHIP_TYPE;
-       candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->clock = 16000000;
-       candevices_p[card]->chip[chipnr]->int_cpu_reg = iCPU_DSC | iCPU_DMC;
-       candevices_p[card]->chip[chipnr]->int_clk_reg = iCLK_SL1 | iCLK_CD0;
-       candevices_p[card]->chip[chipnr]->int_bus_reg = iBUS_CBY | iBUS_DR1;
-       candevices_p[card]->chip[chipnr]->sja_cdr_reg = 0;
-       candevices_p[card]->chip[chipnr]->sja_ocr_reg = 0;
-       pcccan_irq=candevices_p[card]->chip[chipnr]->chip_irq;
-       pcccan_base=candevices_p[card]->chip[chipnr]->chip_base_addr;
+       candev->chip[chipnr]->chip_type=CHIP_TYPE;
+       candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+       candev->chip[chipnr]->clock = 16000000;
+       candev->chip[chipnr]->int_cpu_reg = iCPU_DSC | iCPU_DMC;
+       candev->chip[chipnr]->int_clk_reg = iCLK_SL1 | iCLK_CD0;
+       candev->chip[chipnr]->int_bus_reg = iBUS_CBY | iBUS_DR1;
+       candev->chip[chipnr]->sja_cdr_reg = 0;
+       candev->chip[chipnr]->sja_ocr_reg = 0;
+       pcccan_irq=candev->chip[chipnr]->chip_irq;
+       pcccan_base=candev->chip[chipnr]->chip_base_addr;
 
        return 0;
 }
@@ -229,10 +223,10 @@ int pcccan_init_chip_data(int card, int chipnr)
  * Return Value: The function always returns zero
  * File: src/pcccan.c
  */
-int pcccan_init_obj_data(int chipnr, int objnr)
+int pcccan_init_obj_data(struct chip_t *chip, int objnr)
 {
-       chips_p[chipnr]->msgobj[objnr]->obj_base_addr=(objnr+1)*0x10;
-       chips_p[chipnr]->msgobj[objnr]->flags=0;
+       chip->msgobj[objnr]->obj_base_addr=(objnr+1)*0x10;
+       chip->msgobj[objnr]->flags=0;
        
        return 0;
 }
@@ -249,7 +243,7 @@ int pcccan_init_obj_data(int chipnr, int objnr)
  * Return value: The function returns zero on success or %-ENODEV on failure
  * File: src/pcccan.c
  */
-int pcccan_program_irq(int card)
+int pcccan_program_irq(struct candevice_t *candev)
 {
        return 0;
 }
index 853986a..2736035 100644 (file)
@@ -1,18 +1,13 @@
 /* pcm3680.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
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
        #endif /*request_mem_region*/
 #endif /* 2.4.0 */
 
-/* Basic hardware io address. This is also stored in the hardware structure but
- * we need it global, else we have to change many internal functions.
- * pcm3680_base_addr is initialized in pcm3680_init_chip_data().
- */
-unsigned long pcm3680_base_addr;
-static unsigned long isa_base = 0L; 
-
 /*
  * IO_RANGE is the io-memory range that gets reserved, please adjust according
  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
@@ -59,22 +47,21 @@ static unsigned long isa_base = 0L;
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/template.c
  */
-int pcm3680_request_io(unsigned long io_addr)
+int pcm3680_request_io(struct candevice_t *candev)
 {
         unsigned long remap_addr;
-       if (!request_mem_region(io_addr,IO_RANGE,DEVICE_NAME " - pcm3680")) {
-               CANMSG("Unable to request IO-memory: 0x%lx\n",io_addr);
+       if (!request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME " - pcm3680")) {
+               CANMSG("Unable to request IO-memory: 0x%lx\n",candev->io_addr);
                return -ENODEV;
        }
-       if ( !( remap_addr = (long) ioremap( io_addr, IO_RANGE ) ) ) {
-               CANMSG("Unable to access I/O memory at: 0x%lx\n", io_addr);
-               release_mem_region(io_addr,IO_RANGE);
+       if ( !( remap_addr = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
+               CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
+               release_mem_region(candev->io_addr,IO_RANGE);
                return -ENODEV;
        
        }
-       isa_base=remap_addr-io_addr;
-
-       DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + IO_RANGE - 1);
+       can_base_addr_fixup(candev, remap_addr);
+       DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
        return 0;
 }
 
@@ -90,10 +77,10 @@ int pcm3680_request_io(unsigned long io_addr)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int pcm3680_release_io(unsigned long io_addr)
+int pcm3680_release_io(struct candevice_t *candev)
 {
-       iounmap((void*)isa_base);
-       release_mem_region(io_addr,IO_RANGE);
+       iounmap((void*)candev->dev_base_addr);
+       release_mem_region(candev->io_addr,IO_RANGE);
        return 0;
 }
 
@@ -107,15 +94,15 @@ int pcm3680_release_io(unsigned long io_addr)
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/template.c
  */
-int pcm3680_reset(int card)
+int pcm3680_reset(struct candevice_t *candev)
 {
        int i=0;
        struct chip_t *chip;
        int chipnr;
        
        DEBUGMSG("Resetting pcm3680 hardware ...\n");
-       for(chipnr=0;chipnr<candevices_p[card]->nr_sja1000_chips;chipnr++) {
-               chip=candevices_p[card]->chip[chipnr];
+       for(chipnr=0;chipnr<candev->nr_sja1000_chips;chipnr++) {
+               chip=candev->chip[chipnr];
                pcm3680_write_register(MOD_RM, chip->chip_base_addr+SJAMOD);
                udelay(1000);
                pcm3680_write_register(0x00, chip->chip_base_addr + SJAIER);
@@ -154,12 +141,13 @@ int pcm3680_reset(int card)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int pcm3680_init_hw_data(int card
+int pcm3680_init_hw_data(struct candevice_t *candev
 {
-       candevices_p[card]->res_addr=RESET_ADDR;
-       candevices_p[card]->nr_82527_chips=NR_82527;
-       candevices_p[card]->nr_sja1000_chips=NR_SJA1000;
-       candevices_p[card]->flags &= ~PROGRAMMABLE_IRQ;
+       candev->res_addr=RESET_ADDR;
+       candev->nr_82527_chips=NR_82527;
+       candev->nr_sja1000_chips=NR_SJA1000;
+       candev->nr_all_chips=NR_82527+NR_SJA1000;
+       candev->flags &= ~PROGRAMMABLE_IRQ;
 
        return 0;
 }
@@ -194,17 +182,16 @@ int pcm3680_init_hw_data(int card)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int pcm3680_init_chip_data(int card, int chipnr)
+int pcm3680_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       pcm3680_base_addr = candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->chip_type=CHIP_TYPE;
-       candevices_p[card]->chip[chipnr]->chip_base_addr=
-                       candevices_p[card]->io_addr + 0x200*chipnr;
-       candevices_p[card]->chip[chipnr]->clock = 16000000;
-       candevices_p[card]->chip[chipnr]->int_clk_reg = 0x0;
-       candevices_p[card]->chip[chipnr]->int_bus_reg = 0x0;
-       candevices_p[card]->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
-       candevices_p[card]->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL |
+       candev->chip[chipnr]->chip_type=CHIP_TYPE;
+       candev->chip[chipnr]->chip_base_addr=
+                       candev->io_addr + 0x200*chipnr;
+       candev->chip[chipnr]->clock = 16000000;
+       candev->chip[chipnr]->int_clk_reg = 0x0;
+       candev->chip[chipnr]->int_bus_reg = 0x0;
+       candev->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
+       candev->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL |
                                                                OCR_TX0_LH;
 
        return 0;
@@ -227,10 +214,10 @@ int pcm3680_init_chip_data(int card, int chipnr)
  * Return Value: The function always returns zero
  * File: src/template.c
  */
-int pcm3680_init_obj_data(int chipnr, int objnr)
+int pcm3680_init_obj_data(struct chip_t *chip, int objnr)
 {
-       chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr;
-       chips_p[chipnr]->msgobj[objnr]->flags=0;
+       chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
+       chip->msgobj[objnr]->flags=0;
        
        return 0;
 }
@@ -247,7 +234,7 @@ int pcm3680_init_obj_data(int chipnr, int objnr)
  * Return value: The function returns zero on success or %-ENODEV on failure
  * File: src/template.c
  */
-int pcm3680_program_irq(int card)
+int pcm3680_program_irq(struct candevice_t *candev)
 {
        return 0;
 }
@@ -265,7 +252,7 @@ int pcm3680_program_irq(int card)
  */
 void pcm3680_write_register(unsigned char data, unsigned long address)
 {
-       writeb(data,isa_base+address);
+       writeb(data,address);
 }
 
 /**
@@ -280,7 +267,7 @@ void pcm3680_write_register(unsigned char data, unsigned long address)
  */
 unsigned pcm3680_read_register(unsigned long address)
 {
-       return readb(isa_base+address);
+       return readb(address);
 }
 
 /* !!! Don't change this function !!! */
index 104cbbc..fb6e3dc 100644 (file)
@@ -1,18 +1,13 @@
 /* pikronisa.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
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -31,8 +26,6 @@
  */
 #define IO_RANGE 0x100
 
-static long base = 0L; 
-
 /**
  * pikronisa_request_io: - reserve io memory
  * @io_addr: The reserved memory starts at @io_addr, wich is the module 
@@ -47,16 +40,22 @@ static long base = 0L;
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/pikronisa.c
  */
-int pikronisa_request_io(unsigned long io_addr)
+int pikronisa_request_io(struct candevice_t *candev)
 {
         int remap_addr;
-       if ( !( remap_addr = (long) ioremap( io_addr, IO_RANGE ) ) ) {
-               CANMSG("Unable to access I/O memory at: 0x%lx\n", io_addr);
+       
+       if (!request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME " - pikronisa")) {
+               CANMSG("Unable to request IO-memory: 0x%lx\n",candev->io_addr);
+               return -ENODEV;
+       }
+       if ( !( remap_addr = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) {
+               CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
+               release_mem_region(candev->io_addr,IO_RANGE);
                return -ENODEV;
        
        }
-       base=remap_addr-io_addr;
-       DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + IO_RANGE - 1);
+       can_base_addr_fixup(candev, remap_addr);
+       DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
        return 0;
 }
 
@@ -72,10 +71,11 @@ int pikronisa_request_io(unsigned long io_addr)
  * Return Value: The function always returns zero
  * File: src/pikronisa.c
  */
-int pikronisa_release_io(unsigned long io_addr)
+int pikronisa_release_io(struct candevice_t *candev)
 {
        /* release I/O memory mapping */
-       iounmap((void*)base);
+       iounmap((void*)candev->dev_base_addr);
+       release_mem_region(candev->io_addr,IO_RANGE);
 
        return 0;
 }
@@ -90,10 +90,10 @@ int pikronisa_release_io(unsigned long io_addr)
  * Return Value: The function returns zero on success or %-ENODEV on failure
  * File: src/pikronisa.c
  */
-int pikronisa_reset(int card)
+int pikronisa_reset(struct candevice_t *candev)
 {
        int i;
-       struct chip_t *chip=candevices_p[card]->chip[0];
+       struct chip_t *chip=candev->chip[0];
        unsigned cdr;
        
        pikronisa_write_register(MOD_RM, chip->chip_base_addr+SJAMOD);
@@ -138,12 +138,13 @@ int pikronisa_reset(int card)
  * Return Value: The function always returns zero
  * File: src/pikronisa.c
  */
-int pikronisa_init_hw_data(int card
+int pikronisa_init_hw_data(struct candevice_t *candev
 {
-       candevices_p[card]->res_addr=RESET_ADDR;
-       candevices_p[card]->nr_82527_chips=0;
-       candevices_p[card]->nr_sja1000_chips=1;
-       candevices_p[card]->flags |= PROGRAMMABLE_IRQ*0;
+       candev->res_addr=RESET_ADDR;
+       candev->nr_82527_chips=0;
+       candev->nr_sja1000_chips=1;
+       candev->nr_all_chips=1;
+       candev->flags |= PROGRAMMABLE_IRQ*0;
 
        return 0;
 }
@@ -183,17 +184,15 @@ int pikronisa_init_hw_data(int card)
  * Return Value: The function always returns zero
  * File: src/pikronisa.c
  */
-int pikronisa_init_chip_data(int card, int chipnr)
+int pikronisa_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       /* pikronisa_base_addr = candevices_p[card]->io_addr; */
-       candevices_p[card]->chip[chipnr]->chip_type=CHIP_TYPE;
-       candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->clock = 24000000;
-       candevices_p[card]->chip[chipnr]->int_clk_reg = 0x0;
-       candevices_p[card]->chip[chipnr]->int_bus_reg = 0x0;
-       candevices_p[card]->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
-       candevices_p[card]->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL |
-                                                               OCR_TX0_LH;
+       candev->chip[chipnr]->chip_type=CHIP_TYPE;
+       candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+       candev->chip[chipnr]->clock = 24000000;
+       candev->chip[chipnr]->int_clk_reg = 0x0;
+       candev->chip[chipnr]->int_bus_reg = 0x0;
+       candev->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
+       candev->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL | OCR_TX0_LH;
 
        return 0;
 }
@@ -215,10 +214,10 @@ int pikronisa_init_chip_data(int card, int chipnr)
  * Return Value: The function always returns zero
  * File: src/pikronisa.c
  */
-int pikronisa_init_obj_data(int chipnr, int objnr)
+int pikronisa_init_obj_data(struct chip_t *chip, int objnr)
 {
-       chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr;
-       chips_p[chipnr]->msgobj[objnr]->flags=0;
+       chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
+       chip->msgobj[objnr]->flags=0;
        return 0;
 }
 
@@ -234,7 +233,7 @@ int pikronisa_init_obj_data(int chipnr, int objnr)
  * Return value: The function returns zero on success or %-ENODEV on failure
  * File: src/pikronisa.c
  */
-int pikronisa_program_irq(int card)
+int pikronisa_program_irq(struct candevice_t *candev)
 {
        return 0;
 }
@@ -252,9 +251,9 @@ int pikronisa_program_irq(int card)
  */
 void pikronisa_write_register(unsigned char data, unsigned long address)
 {
-       /*DEBUGMSG("pikronisa_write_register: base=0x%lx addr=0x%lx data=0x%x",
-               base,address,data);*/
-       writeb(data,base+address);
+       /*DEBUGMSG("pikronisa_write_register: addr=0x%lx data=0x%x",
+               address,data);*/
+       writeb(data,address);
 }
 
 /**
@@ -269,7 +268,7 @@ void pikronisa_write_register(unsigned char data, unsigned long address)
  */
 unsigned pikronisa_read_register(unsigned long address)
 {
-       return readb(base+address);
+       return readb(address);
 }
 
 /* !!! Don't change this function !!! */
index 6bbfd8d..72ede89 100644 (file)
@@ -1,18 +1,13 @@
 /* pip.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
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include "../include/pip.h"
 #include "../include/i82527.h"
 
-int pip5_request_io(unsigned long io_addr)
+int pip5_request_io(struct candevice_t *candev)
 {
-       if (io_addr != 0x8000) {
+       if (candev->io_addr != 0x8000) {
                CANMSG("Invalid base io address\n");
                CANMSG("The PIP5 uses a fixed base address of 0x8000,\n");
                CANMSG("please consult your user manual.\n");
                return -ENODEV;
        }
-       if (check_region(io_addr,0x100)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr);
+       if (!can_request_io_region(candev->io_addr,0x100,DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
                return -ENODEV;
        }
-       else if(check_region(io_addr+0x102,0x01)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr+0x102);
+       else if(!can_request_io_region(candev->io_addr+0x102,0x01,DEVICE_NAME)) {
+               can_release_io_region(candev->io_addr,0x100);
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr+0x102);
                return -ENODEV;
        }
        else {
-               request_region(io_addr,0x100,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + 0x100 - 1);
-               request_region(io_addr+0x102,0x01,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx\n", io_addr+0x102);
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + 0x100 - 1);
+               DEBUGMSG("Registered IO-memory: 0x%lx\n", candev->io_addr+0x102);
        }
        return 0;
 }
 
-int pip6_request_io(unsigned long io_addr)
+int pip6_request_io(struct candevice_t *candev)
 {
-       if ( (io_addr != 0x1000)&&(io_addr != 0x8000)&&(io_addr != 0xe000)) {
+       if ( (candev->io_addr != 0x1000)&&(candev->io_addr != 0x8000)&&(candev->io_addr != 0xe000)) {
                CANMSG("Invalid base io address\n");
                CANMSG("Valid values for the PIP6 are: 0x1000, 0x8000 or 0xe000\n");
                CANMSG("Please consult your user manual.\n");
                return -ENODEV;
        }
-       if (check_region(io_addr,0x100)) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr);
+       if (!can_request_io_region(candev->io_addr,0x100, DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
                return -ENODEV;
        }
-       else if (check_region(0x804, 0x02)) {
+       else if (!can_request_io_region(0x804,0x02,DEVICE_NAME)) {
+               can_release_io_region(candev->io_addr,0x100);
                CANMSG("Unable to open port: 0x%x\n", 0x804);
                return -ENODEV;
        }
        else {
-               request_region(io_addr,0x100, DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + 0x100 -1);
-               request_region(0x804,0x02,DEVICE_NAME);
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + 0x100 -1);
                DEBUGMSG("Registered IO-memory : 0x%x - 0x%x\n",0x804,0x805);
        }
        return 0;
 }
 
-int pip5_release_io(unsigned long io_addr)
+int pip5_release_io(struct candevice_t *candev)
 {
-       release_region(io_addr,0x100);
-       release_region(io_addr+0x102,0x01);
+       can_release_io_region(candev->io_addr,0x100);
+       can_release_io_region(candev->io_addr+0x102,0x01);
 
        return 0;
 }
 
-int pip6_release_io(unsigned long io_addr)
+int pip6_release_io(struct candevice_t *candev)
 {
-       release_region(io_addr,0x100);
-       release_region(0x804,0x02);
+       can_release_io_region(candev->io_addr,0x100);
+       can_release_io_region(0x804,0x02);
 
        return 0;
 }
 
-int pip_reset(int card)
+int pip_reset(struct candevice_t *candev)
 {
        int i=0, res_value=0;
 
-       DEBUGMSG("Resetting %s hardware ...\n", candevices_p[card]->hwname);
-       if (!strcmp(candevices_p[card]->hwname,"pip5"))
+       DEBUGMSG("Resetting %s hardware ...\n", candev->hwname);
+       if (!strcmp(candev->hwname,"pip5"))
                res_value = 0xcf;
        else
                res_value = 0x01;
        while (i < 1000000) {
                i++;
-               outb(res_value,candevices_p[card]->res_addr);
+               outb(res_value,candev->res_addr);
        }
-       outb(0x0,candevices_p[card]->res_addr);
+       outb(0x0,candev->res_addr);
 
        /* Check hardware reset status */
        i=0;
-       while ( (inb(candevices_p[card]->io_addr+iCPU) & iCPU_RST) && (i<=15)) {
+       while ( (inb(candev->io_addr+iCPU) & iCPU_RST) && (i<=15)) {
                udelay(20000);
                i++;
        }
@@ -123,70 +116,71 @@ int pip_reset(int card)
        return 0;
 }
 
-int pip_init_hw_data(int card
+int pip_init_hw_data(struct candevice_t *candev
 {
-       if (!strcmp(candevices_p[card]->hwname,"pip5"))
-               candevices_p[card]->res_addr=candevices_p[card]->io_addr+0x102;
+       if (!strcmp(candev->hwname,"pip5"))
+               candev->res_addr=candev->io_addr+0x102;
        else
-               candevices_p[card]->res_addr=0x805;
-       candevices_p[card]->nr_82527_chips=1;
-       candevices_p[card]->nr_sja1000_chips=0;
-       candevices_p[card]->flags |= PROGRAMMABLE_IRQ;
+               candev->res_addr=0x805;
+       candev->nr_82527_chips=1;
+       candev->nr_sja1000_chips=0;
+       candev->nr_all_chips=1;
+       candev->flags |= PROGRAMMABLE_IRQ;
 
        return 0;
 }
 
-int pip_init_chip_data(int card, int chipnr)
+int pip_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       candevices_p[card]->chip[chipnr]->chip_type="i82527";
-       candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->clock = 16000000;
-       if (!strcmp(candevices_p[card]->hwname,"pip5"))
-               candevices_p[card]->chip[chipnr]->int_cpu_reg = iCPU_DSC;
+       candev->chip[chipnr]->chip_type="i82527";
+       candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+       candev->chip[chipnr]->clock = 16000000;
+       if (!strcmp(candev->hwname,"pip5"))
+               candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
        else
-               candevices_p[card]->chip[chipnr]->int_cpu_reg = 0x0;
-       candevices_p[card]->chip[chipnr]->int_clk_reg = iCLK_SL1;
-       candevices_p[card]->chip[chipnr]->int_bus_reg = iBUS_CBY;
-       candevices_p[card]->chip[chipnr]->sja_cdr_reg = 0;
-       candevices_p[card]->chip[chipnr]->sja_ocr_reg = 0;
+               candev->chip[chipnr]->int_cpu_reg = 0x0;
+       candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
+       candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
+       candev->chip[chipnr]->sja_cdr_reg = 0;
+       candev->chip[chipnr]->sja_ocr_reg = 0;
 
        return 0;
 }
 
-int pip_init_obj_data(int chipnr, int objnr)
+int pip_init_obj_data(struct chip_t *chip, int objnr)
 {
-       chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr+(objnr+1)*0x10;
-       chips_p[chipnr]->msgobj[objnr]->flags=0;
+       chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
+       chip->msgobj[objnr]->flags=0;
        
        return 0;
 }
 
-int pip5_program_irq(int card)
+int pip5_program_irq(struct candevice_t *candev)
 {
-       outb(0x01, candevices_p[card]->res_addr);
-       switch (candevices_p[card]->chip[0]->chip_irq) {
-               case  3: { outb(0x03, candevices_p[card]->res_addr); break; }
-               case  4: { outb(0x05, candevices_p[card]->res_addr); break; }
-               case  5: { outb(0x07, candevices_p[card]->res_addr); break; }
-               case 10: { outb(0x09, candevices_p[card]->res_addr); break; }
-               case 11: { outb(0x0c, candevices_p[card]->res_addr); break; }
-               case 15: { outb(0x0d, candevices_p[card]->res_addr); break; }
+       outb(0x01, candev->res_addr);
+       switch (candev->chip[0]->chip_irq) {
+               case  3: { outb(0x03, candev->res_addr); break; }
+               case  4: { outb(0x05, candev->res_addr); break; }
+               case  5: { outb(0x07, candev->res_addr); break; }
+               case 10: { outb(0x09, candev->res_addr); break; }
+               case 11: { outb(0x0c, candev->res_addr); break; }
+               case 15: { outb(0x0d, candev->res_addr); break; }
                default: {
                CANMSG("Supplied interrupt is not supported by the hardware\n");
                CANMSG("Please consult your user manual.\n");
                return -ENODEV;
                }
        }
-       outb(0x00, candevices_p[card]->res_addr);
+       outb(0x00, candev->res_addr);
 
        return 0;
 }
 
-int pip6_program_irq(int card)
+int pip6_program_irq(struct candevice_t *candev)
 {
        unsigned char can_int = 0, can_addr = 0;
 
-       can_int = candevices_p[card]->chip[0]->chip_irq;
+       can_int = candev->chip[0]->chip_irq;
        if ((can_int != 3) && (can_int != 4) && (can_int != 5) && (can_int != 6)
                && (can_int != 7) && (can_int != 9) && (can_int != 10) && 
                (can_int != 11) && (can_int != 12) && (can_int != 14) && 
@@ -196,7 +190,7 @@ int pip6_program_irq(int card)
                CANMSG("Please consult your user manual.\n");
                return -ENODEV;
        }
-       switch (candevices_p[card]->io_addr) {
+       switch (candev->io_addr) {
                case 0x1000: { can_addr = 0x01; break; }
                case 0x8000: { can_addr = 0x02; break; }
                case 0xe000: { can_addr = 0x03; break; }
index 79309e0..fb573be 100644 (file)
@@ -1,25 +1,20 @@
 /* proc.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
  */ 
 
 #define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/autoconf.h>
-#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
-#define MODVERSIONS
-#endif
-
-#if defined (MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 
 #include <linux/version.h>
 #include <linux/kernel.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
 #include <linux/malloc.h>
 #else
 #include <linux/slab.h>
 #include "../include/proc.h"
 #include "../include/setup.h"
 
-int add_channel_to_procdir(void);
+int add_channel_to_procdir(struct candevice_t *candev);
 int remove_channel_from_procdir(void);
-int add_object_to_procdir(void);
+int add_object_to_procdir(int chip_nr);
 int remove_object_from_procdir(void);
 
 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
 static int candev_readlink(struct proc_dir_entry *de, char *page);
 #endif
 
-static int bc=0; /* static counter for each hardware board */
 static int cc=0; /* static counter for each CAN chip */
-static int oc=0; /* static counter for each message object */
 
 struct canproc_t can_proc_base;
 struct canproc_t *base=&can_proc_base;
@@ -101,6 +94,8 @@ int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *par
  */
 int can_init_procdir(void)
 {
+       int board;
+       struct candevice_t *candev;
 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
        base->can_proc_entry = new_can_proc_entry(0, "can", S_IFDIR | S_IRUGO | 
                                        S_IXUGO, 0, &proc_root);
@@ -111,8 +106,9 @@ int can_init_procdir(void)
        if (base->can_proc_entry == NULL)
                return -ENODEV;
 
-       for (bc=0; bc<hardware_p->nr_boards; bc++) {
-               add_channel_to_procdir();
+       for (board=0; board<hardware_p->nr_boards; board++) {
+               candev=hardware_p->candevice[board];
+               if(candev) add_channel_to_procdir(candev);
        } 
 
        return 0;
@@ -133,12 +129,11 @@ int can_delete_procdir(void)
        return 0;
 }
 
-int add_channel_to_procdir(void)
+int add_channel_to_procdir(struct candevice_t *candev)
 {
        int i=0;
 
-       for (i=0; i < candevices_p[bc]->nr_82527_chips + 
-                       candevices_p[bc]->nr_sja1000_chips; i++) {
+       for (i=0; i < candev->nr_all_chips; i++) {
 
                base->channel[cc] = (struct channelproc_t *)
                        kmalloc(sizeof(struct channelproc_t), GFP_KERNEL);
@@ -163,7 +158,7 @@ int add_channel_to_procdir(void)
                if (base->channel[cc]->ch_entry == NULL)
                        return -ENODEV;
 
-               add_object_to_procdir();
+               add_object_to_procdir(cc);
 
                cc++;
        } 
@@ -192,60 +187,56 @@ int remove_channel_from_procdir(void)
 }
 
 
-int add_object_to_procdir(void)
+int add_object_to_procdir(int chip_nr)
 {
-       int i=0, obj=0;
+       int i, max_objects;
 
-       if (!strcmp(chips_p[cc]->chip_type,"i82527"))
-               obj=15;
-       if (!strcmp(chips_p[cc]->chip_type,"sja1000"))
-               obj=1;
+       max_objects=chips_p[chip_nr]->max_objects;
 
-       for (i=0; i<obj; i++) {
-               oc=i;
-               base->channel[cc]->object[i] = (struct objectproc_t *)
+       for (i=0; i<max_objects; i++) {
+               base->channel[chip_nr]->object[i] = (struct objectproc_t *)
                        kmalloc(sizeof(struct objectproc_t),GFP_KERNEL);
                                
                                
-               if (base->channel[cc]->object[i] == NULL)
+               if (base->channel[chip_nr]->object[i] == NULL)
                        return -ENOMEM;
-               else if (add_mem_to_list( base->channel[cc]->object[i]))
+               else if (add_mem_to_list( base->channel[chip_nr]->object[i]))
                        return -ENOMEM;
 
-               sprintf(base->channel[cc]->object[i]->obj_name,"object%d",i);
-               sprintf(base->channel[cc]->object[i]->lnk_name,"dev");
+               sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
+               sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
                                                                
 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
-               base->channel[cc]->object[i]->obj_entry=new_can_proc_entry(
-                               0, base->channel[cc]->object[i]->obj_name,
+               base->channel[chip_nr]->object[i]->obj_entry=new_can_proc_entry(
+                               0, base->channel[chip_nr]->object[i]->obj_name,
                                S_IFDIR | S_IRUGO | S_IXUGO, 0, 
-                               base->channel[cc]->ch_entry);
-               if (base->channel[cc]->object[i]->obj_entry == NULL)
+                               base->channel[chip_nr]->ch_entry);
+               if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
                        return -ENODEV;
-               base->channel[cc]->object[i]->lnk = new_can_proc_entry(
-                               0, base->channel[cc]->object[i]->lnk_name, 
+               base->channel[chip_nr]->object[i]->lnk = new_can_proc_entry(
+                               0, base->channel[chip_nr]->object[i]->lnk_name, 
                                S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO,
-                               0, base->channel[cc]->object[i]->obj_entry);
-               if (base->channel[cc]->object[i]->lnk == NULL)
+                               0, base->channel[chip_nr]->object[i]->obj_entry);
+               if (base->channel[chip_nr]->object[i]->lnk == NULL)
                        return -ENODEV;
-               sprintf(base->channel[cc]->object[i]->lnk_dev,"/dev/can");
-               base->channel[cc]->object[i]->lnk->readlink_proc =
+               sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can");
+               base->channel[chip_nr]->object[i]->lnk->readlink_proc =
                                                                candev_readlink;
 
 #else
-               base->channel[cc]->object[i]->obj_entry = create_proc_entry(
-                               base->channel[cc]->object[i]->obj_name,
+               base->channel[chip_nr]->object[i]->obj_entry = create_proc_entry(
+                               base->channel[chip_nr]->object[i]->obj_name,
                                S_IFDIR | S_IRUGO | S_IXUGO,
-                               base->channel[cc]->ch_entry);
-               if (base->channel[cc]->object[i]->obj_entry == NULL)
+                               base->channel[chip_nr]->ch_entry);
+               if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
                        return -ENODEV;
-               sprintf(base->channel[cc]->object[i]->lnk_dev,"/dev/can%d",
-                       chips_p[cc]->msgobj[i]->minor);
-               base->channel[cc]->object[i]->lnk = proc_symlink(
-                               base->channel[cc]->object[i]->lnk_name,
-                               base->channel[cc]->object[i]->obj_entry,
-                               base->channel[cc]->object[i]->lnk_dev);
-               if (base->channel[cc]->object[i]->lnk == NULL)
+               sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can%d",
+                       chips_p[chip_nr]->msgobj[i]->minor);
+               base->channel[chip_nr]->object[i]->lnk = proc_symlink(
+                               base->channel[chip_nr]->object[i]->lnk_name,
+                               base->channel[chip_nr]->object[i]->obj_entry,
+                               base->channel[chip_nr]->object[i]->lnk_dev);
+               if (base->channel[chip_nr]->object[i]->lnk == NULL)
                        return -ENODEV;
 #endif
 
@@ -257,10 +248,7 @@ int remove_object_from_procdir(void)
 {
        int i=0, obj=0;
 
-       if (!strcmp(chips_p[cc]->chip_type,"i82527"))
-               obj=15;
-       if (!strcmp(chips_p[cc]->chip_type,"sja1000"))
-               obj=1;
+       obj=chips_p[cc]->max_objects;
 
        for (i=0; i<obj; i++) {
 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
index 1111401..64b2415 100644 (file)
@@ -1,24 +1,19 @@
 /* read.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
  */
 
 #define __NO_VERSION__
 #include <linux/module.h> 
 
 #include <linux/autoconf.h>
-#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
-#define MODVERSIONS
-#endif
-
-#if defined (MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 
 #include <linux/version.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
 #include <linux/malloc.h>
 #else
 #include <linux/slab.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 canfifo_t *fifo
+inline ssize_t can_std_read(struct file *file, struct canque_ends_t *qends
                        struct msgobj_t *obj, char *buffer, size_t length)
 {
-       int can_timeout, ret;
-       int bytes_avail = 0, bytes_to_copy = 0;
-
-       cli();
-       if (fifo->rx_readp == fifo->rx_writep) {        // Buffer is empty
+       int ret;
+       int bytes_to_copy;
+       struct canque_edge_t *qedge;
+       struct canque_slot_t *slot;
+       
+       ret=canque_test_outslot(qends, &qedge, &slot);
+       if(ret<0){
                if (file->f_flags & O_NONBLOCK) {
-                       sti();
                        return -EAGAIN;
                }
-               obj->ret = 0;
-               can_timeout = interruptible_sleep_on_timeout(&fifo->readq,
-                                                               CANTIMEOUT);
-               sti();
-               if (signal_pending(current)) {
-                       DEBUGMSG("Rx interrupted\n");
-                       return -EINTR;
-               }
-               if (!can_timeout) {
-                       DEBUGMSG("no data received\n");
-                       return 0;
+               ret=canque_get_outslot_wait_kern(qends, &qedge, &slot);
+               if(ret<0){
+                       if (signal_pending(current)) {
+                               DEBUGMSG("Rx interrupted\n");
+                               return -EINTR;
+                       }
+                       /*if (!can_timeout) {
+                               DEBUGMSG("no data received\n");
+                               return 0;
+                       }*/
+                       return -EIO;
                }
-               if (obj->ret < 0)
-                       return obj->ret;
        }
-       /* Calculate available bytes in the buffer */
-       cli();
-       bytes_avail = ((int)fifo->rx_readp < (int)fifo->rx_writep) ?
-                       ((int)fifo->rx_writep - (int)fifo->rx_readp) :
-                       ((int)fifo->rx_writep - (int)fifo->rx_readp + 
-                                                       (int)fifo->rx_size);
-       sti();
-               
-       bytes_to_copy = (length < bytes_avail) ? length : bytes_avail;
-       ret = bytes_to_copy;
-
-       /* printk(KERN_CRIT "can RxFIFO b:%x e:%x bs:%x msg:%x rp:%x wp:%x btc:%x\n",
-              fifo->buf_rx_entry, fifo->buf_rx_entry+MAX_BUF_LENGTH,
-              fifo->rx_size, sizeof(struct canmsg_t),
-              fifo->rx_readp, fifo->rx_writep, bytes_to_copy); */
-
-
-       /* Copy the data to user space */
+       
+       copy_to_user(buffer, &slot->msg, sizeof(struct canmsg_t));
+       canque_free_outslot(qends, qedge, slot);
+       buffer += sizeof(struct canmsg_t);
+       bytes_to_copy = length-sizeof(struct canmsg_t);
+       
        while (bytes_to_copy > 0) {
-                      
-               
-               copy_to_user(buffer, fifo->rx_readp, sizeof(struct canmsg_t));
+               ret=canque_test_outslot(qends, &qedge, &slot);
+               if(ret<0)
+                       break;
+               copy_to_user(buffer, &slot->msg, sizeof(struct canmsg_t));
+               canque_free_outslot(qends, qedge, slot);
                buffer += sizeof(struct canmsg_t);
                bytes_to_copy -= sizeof(struct canmsg_t);
-               fifo->rx_readp++;
-               if (fifo->rx_readp >= fifo->buf_rx_entry + MAX_BUF_LENGTH)
-                       fifo->rx_readp = fifo->buf_rx_entry;
-
-               /* printk(KERN_CRIT "can RxFIFO rp%x\n",fifo->rx_readp); */
        }
 
-       return ret;
+       return length-bytes_to_copy;
 }
 
 /* This is the 'RTR' read handler for remote transmission request messages */
@@ -160,12 +139,18 @@ inline ssize_t can_rtr_read(struct chip_t *chip, struct msgobj_t *obj,
 
 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 chip_t *chip;
-       struct canfifo_t *fifo;
        struct canmsg_t read_msg;
+       struct canque_ends_t *qends;
        int ret=0;
 
+       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 read less bytes than a CAN message, \n");
                DEBUGMSG("this will always return zero.\n");
@@ -177,25 +162,23 @@ ssize_t can_read(struct file *file, char *buffer, size_t length, loff_t *offset)
                length = 8 * sizeof(struct canmsg_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;
        }
+       qends = canuser->qends;
        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;
-       }
 
        copy_from_user(&read_msg, buffer, sizeof(struct canmsg_t));
        if (read_msg.flags & MSG_RTR)
                ret = can_rtr_read(chip, obj, buffer);
        else
-               ret = can_std_read(file, fifo, obj, buffer, length);
+               ret = can_std_read(file, qends, obj, buffer, length);
 
        return ret;
 }
index 27b2d22..efdb212 100644 (file)
@@ -1,20 +1,13 @@
 /* select.c
  * Header file for the Linux CAN-bus driver.
  * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
+ * Added by Pavel Pisa - OCERA team member
+ * email:pisa@cmp.felk.cvut.cz
  * This software is released under the GPL-License.
- * Version 0.7.1-pi2  15 Nov 2002
- * 
- * added by Pavel Pisa pisa@cmp.felk.cvut.cz
+ * 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
 
 #include <linux/version.h>
 #include <linux/poll.h>
 
 unsigned int can_poll(struct file *file, poll_table *wait)
 {
-        unsigned int mask = 0;
+       struct canuser_t *canuser = (struct canuser_t*)(file->private_data);
+       struct canque_ends_t *qends;
        struct msgobj_t *obj;
-       struct canfifo_t *fifo;
+        unsigned int mask = 0;
+       unsigned long flags;
+       struct canque_edge_t *edge;
+       struct list_head *entry;
+       int full=0;
+       int i;
 
-       /* Initialize hardware pointers */
-       if ( (obj = objects_p[MINOR_NR]) == NULL) {
-               CANMSG("Could not assign buffer structure\n");
-               return 0;
-       }
-       if ( (fifo = obj->fifo) == NULL) {
-               CANMSG("Could not assign buffer memory.\n");
-               return 0;
+       if(!canuser || (canuser->magic != CAN_USER_MAGIC)){
+               CANMSG("can_close: bad canuser magic\n");
+               return -ENODEV;
        }
+       
+       obj = canuser->msgobj;
+       qends = canuser->qends;
 
-        if (file->f_mode & FMODE_WRITE) {
-                poll_wait(file, &fifo->writeq, wait);
-        }
         if (file->f_mode & FMODE_READ) {
-                poll_wait(file, &fifo->readq, wait);
-        }
-        if ((file->f_mode & FMODE_READ)&&
-           (fifo->rx_readp != fifo->rx_writep)) {
-                 mask |= POLLIN | POLLRDNORM;
+                poll_wait(file, &qends->endinfo.fileinfo.readq, wait);
+               for(i=CANQUEUE_PRIO_NR;--i>=0;) {
+                       if(!list_empty(&qends->active[i]))
+                               mask |= POLLIN | POLLRDNORM;
+               }
         }
-        if ((file->f_mode & FMODE_WRITE)&&
-           (fifo->tx_readp == fifo->tx_writep)) {
-                 mask |= POLLOUT | POLLWRNORM;
+
+        if ((file->f_mode & FMODE_WRITE) && !(file->f_flags & O_SYNC)) {
+                poll_wait(file, &qends->endinfo.fileinfo.writeq, wait);
+
+               spin_lock_irqsave(&qends->ends_lock, flags);
+               list_for_each(entry,&qends->inlist){
+                       edge=list_entry(entry,struct canque_edge_t,inpeers);
+                       if(canque_fifo_test_fl(&edge->fifo,FULL))
+                               full=1;
+               }
+               spin_unlock_irqrestore(&qends->ends_lock, flags);
+
+               if(!full)
+                       mask |= POLLOUT | POLLWRNORM;
+       }
+
+        if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_SYNC)) {
+                poll_wait(file, &qends->endinfo.fileinfo.emptyq, wait);
+
+               spin_lock_irqsave(&qends->ends_lock, flags);
+               list_for_each(entry,&qends->inlist){
+                       edge=list_entry(entry,struct canque_edge_t,inpeers);
+                       if(!canque_fifo_test_fl(&edge->fifo,EMPTY))
+                               full=1;
+               }
+               spin_unlock_irqrestore(&qends->ends_lock, flags);
+
+               if(!full)
+                       mask |= POLLOUT | POLLWRNORM;
        }
        return mask;
 }
index a8f76cc..d234eb9 100644 (file)
@@ -1,33 +1,30 @@
 /* setup.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
  */ 
 
 #define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/autoconf.h>
-#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
-#define MODVERSIONS
-#endif
-
-#if defined (MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 
 #include <linux/version.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
 #include <linux/malloc.h>
 #else
 #include <linux/slab.h>
 #endif
 #include <linux/fs.h>
+#include <linux/ioport.h>
 
 #include ".supported_cards.h"
 
 #include "../include/main.h"
+#include "../include/devcommon.h"
 #include "../include/setup.h"
 #include "../include/pip.h"
 #include "../include/pccan.h"
@@ -61,10 +58,10 @@ extern int bfadcan_register(struct hwspecops_t *hwspecops);
 extern int pikronisa_register(struct hwspecops_t *hwspecops);
 
 int init_device_struct(int card);
-int init_hwspecops(int card);
-int init_chip_struct(int card);
-int init_obj_struct(int card, int chip);
-int init_chipspecops(int card, int chipnr);
+int init_hwspecops(struct candevice_t *candev);
+int init_chip_struct(struct candevice_t *candev);
+int init_obj_struct(struct candevice_t *candev, struct chip_t *hostchip, int minorbase);
+int init_chipspecops(struct candevice_t *candev, int chipnr);
 
 int add_mem_to_list(void *address_p)
 {
@@ -144,6 +141,39 @@ int del_mem_list(void)
        return 0;
 }
 
+int can_request_io_region(unsigned long start, unsigned long n, const char *name)
+{
+    #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
+       if(check_region(start,n)) return 0;
+       request_region(start,n,name);
+       return 1;
+    #else
+       return (request_region(start,n,name))?1:0;
+    #endif
+}
+
+void can_release_io_region(unsigned long start, unsigned long n)
+{
+       release_region(start,n);
+}
+
+/* This function shifts all base address structures acording to address
+   translation between physical and virtual address mappings */
+int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base)
+{
+       unsigned long offs;
+       int i, j;
+       
+       offs=new_base-candev->dev_base_addr;
+       candev->dev_base_addr=new_base;
+       for(i=0;i<candev->nr_all_chips;i++){
+               candev->chip[i]->chip_base_addr += offs;
+               for(j=0;j<candev->chip[i]->max_objects;j++)
+                       candev->chip[i]->msgobj[j]->obj_base_addr += offs;
+       }
+       return 0;
+}
+
 /* The function init_hw_struct is used to initialize the hardware structure. */
 int init_hw_struct(void)
 {
@@ -168,32 +198,40 @@ int init_hw_struct(void)
  */
 int init_device_struct(int card)
 {
-       hardware_p->candevice[card]=(struct candevice_t *)kmalloc(sizeof(struct candevice_t),GFP_KERNEL);
-       if (hardware_p->candevice[card]==NULL)
+       struct candevice_t *candev;
+       
+       candev=(struct candevice_t *)kmalloc(sizeof(struct candevice_t),GFP_KERNEL);
+       if (candev==NULL)
                return -ENOMEM;
        else
-               if ( add_mem_to_list(hardware_p->candevice[card]) )
+               if ( add_mem_to_list(candev) )
                        return -ENOMEM;
 
-       candevices_p[card]=hardware_p->candevice[card];
+        memset(candev, 0, sizeof(struct candevice_t));
+
+       hardware_p->candevice[card]=candev;
+       candev->candev_idx=card;
+
+       candev=candev;
 
-       hardware_p->candevice[card]->hwname=hw[card];
-       hardware_p->candevice[card]->io_addr=io[card];
+       candev->hwname=hw[card];
+       candev->io_addr=io[card];
+       candev->dev_base_addr=io[card];
 
-       hardware_p->candevice[card]->hwspecops=(struct hwspecops_t *)kmalloc(sizeof(struct hwspecops_t),GFP_KERNEL);
-       if (hardware_p->candevice[card]->hwspecops==NULL)
+       candev->hwspecops=(struct hwspecops_t *)kmalloc(sizeof(struct hwspecops_t),GFP_KERNEL);
+       if (candev->hwspecops==NULL)
                return -ENOMEM;
        else
-               if ( add_mem_to_list(hardware_p->candevice[card]->hwspecops) )
+               if ( add_mem_to_list(candev->hwspecops) )
                        return -ENOMEM;
 
-       if (init_hwspecops(card))
+       if (init_hwspecops(candev))
                return -ENODEV;
 
-       if (candevices_p[card]->hwspecops->init_hw_data(card))
+       if (candev->hwspecops->init_hw_data(candev))
                return -ENODEV;
 
-       if (init_chip_struct(card))
+       if (init_chip_struct(candev))
                return -ENODEV;
 
        return 0;
@@ -202,38 +240,44 @@ int init_device_struct(int card)
 /* The function init_chip_struct is used to initialize all chip_t structures
  * on one hardware board.
  */
-int init_chip_struct(int card)
+int init_chip_struct(struct candevice_t *candev)
 {
        static int irq_count=0;
        int i=0;
 
        /* Alocate and initialize the chip structures */
-       for (i=0; i < candevices_p[card]->nr_82527_chips+candevices_p[card]->nr_sja1000_chips; i++) {
-               candevices_p[card]->chip[i]=(struct chip_t *)kmalloc(sizeof(struct chip_t),GFP_KERNEL);
-               if (candevices_p[card]->chip[i]==NULL)
+       for (i=0; i < candev->nr_all_chips; i++) {
+               candev->chip[i]=(struct chip_t *)kmalloc(sizeof(struct chip_t),GFP_KERNEL);
+               if (candev->chip[i]==NULL)
                        return -ENOMEM;
                else
-                       if ( add_mem_to_list(candevices_p[card]->chip[i]) )
+                       if ( add_mem_to_list(candev->chip[i]) )
                                return -ENOMEM;
 
-               candevices_p[card]->chip[i]->chipspecops=(struct chipspecops_t *)kmalloc(sizeof(struct chipspecops_t),GFP_KERNEL);
-               if (candevices_p[card]->chip[i]->chipspecops==NULL)
+               memset(candev->chip[i], 0, sizeof(struct chip_t));
+               
+               candev->chip[i]->write_register=candev->hwspecops->write_register;
+               candev->chip[i]->read_register=candev->hwspecops->read_register;
+
+               candev->chip[i]->chipspecops=(struct chipspecops_t *)kmalloc(sizeof(struct chipspecops_t),GFP_KERNEL);
+               if (candev->chip[i]->chipspecops==NULL)
                        return -ENOMEM;
                else
-                       if ( add_mem_to_list(candevices_p[card]->chip[i]->chipspecops) )
+                       if ( add_mem_to_list(candev->chip[i]->chipspecops) )
                                return -ENOMEM;
 
-               chips_p[irq_count]=candevices_p[card]->chip[i];
-               candevices_p[card]->chip[i]->hostdevice=candevices_p[card];
-               candevices_p[card]->chip[i]->chip_irq=irq[irq_count];
-               candevices_p[card]->chip[i]->flags=0x0;
+               chips_p[irq_count]=candev->chip[i];
+               candev->chip[i]->chip_idx=i;
+               candev->chip[i]->hostdevice=candev;
+               candev->chip[i]->chip_irq=irq[irq_count];
+               candev->chip[i]->flags=0x0;
 
-               candevices_p[card]->hwspecops->init_chip_data(card,i);
+               candev->hwspecops->init_chip_data(candev,i);
 
-               if (init_chipspecops(card,i))
+               if (init_chipspecops(candev,i))
                        return -ENODEV;
 
-               init_obj_struct(card, irq_count);
+               init_obj_struct(candev, candev->chip[i], minor[irq_count]);
 
                irq_count++;
        } 
@@ -241,46 +285,47 @@ int init_chip_struct(int card)
        return 0;
 }
 
-int init_obj_struct(int card, int chip)
+int init_obj_struct(struct candevice_t *candev, struct chip_t *hostchip, int minorbase)
 {
+       struct canque_ends_t *qends;
        static int obj_count=0;
-       int i=0,max_objects=0;
+       int i,max_objects;
+       struct msgobj_t *obj;
 
-       if (!strcmp(chips_p[chip]->chip_type,"i82527")) 
-               max_objects=15;
-       else
-               max_objects=1;
+       max_objects=hostchip->max_objects;
        for (i=0; i<max_objects; i++) {
-               chips_p[chip]->msgobj[i]=(struct msgobj_t *)kmalloc(sizeof(struct msgobj_t),GFP_KERNEL);
-               if (chips_p[chip]->msgobj[i] == NULL) 
+               obj=(struct msgobj_t *)kmalloc(sizeof(struct msgobj_t),GFP_KERNEL);
+               hostchip->msgobj[i]=obj;
+               if (obj == NULL) 
                        return -ENOMEM;
                else
-                       if ( add_mem_to_list(chips_p[chip]->msgobj[i]) )
+                       if ( add_mem_to_list(obj) )
                                return -ENOMEM;
 
-               chips_p[chip]->msgobj[i]->fifo=(struct canfifo_t *)kmalloc(sizeof(struct canfifo_t),GFP_KERNEL);
-               if (chips_p[chip]->msgobj[i]->fifo == NULL)
-                       return -ENOMEM;
-               else
-                       if ( add_mem_to_list(chips_p[chip]->msgobj[i]->fifo) )
-                               return -ENOMEM;
+               memset(obj, 0, sizeof(struct msgobj_t));
+
+               atomic_set(&obj->obj_used,0);
+               INIT_LIST_HEAD(&obj->obj_users);
+               qends = (struct canque_ends_t *)kmalloc(sizeof(struct canque_ends_t), GFP_KERNEL);
+               if(qends == NULL) return -ENOMEM;
+               if(add_mem_to_list(qends)) return -ENOMEM;
+               memset(qends, 0, sizeof(struct canque_ends_t));
+               obj->hostchip=hostchip;
+               obj->object=i+1;
+               obj->qends=qends;
+               obj->tx_qedge=NULL;
+               obj->tx_slot=NULL;
+               obj->flags = 0x0;
+
+               canqueue_ends_init_chip(qends, hostchip, obj);
                
-               if (minor[0] == -1) {
-                       objects_p[obj_count]=chips_p[chip]->msgobj[i];
-                       objects_p[obj_count]->hostchip=chips_p[chip];
-                       objects_p[obj_count]->object=i+1;
-                       objects_p[obj_count]->minor=obj_count;
-               }
-               else {
-                       objects_p[minor[chip]+i]=chips_p[chip]->msgobj[i];
-                       objects_p[minor[chip]+i]->hostchip=chips_p[chip];
-                       objects_p[minor[chip]+i]->object=i+1;
-                       objects_p[minor[chip]+i]->minor=minor[chip]+i;
-               }
+               if (minorbase == -1) minorbase=obj_count;
+               if ((minorbase >= 0) && (minorbase+i<MAX_TOT_MSGOBJS)){
+                 objects_p[minorbase+i]=obj;
+                 obj->minor=minorbase+i;
+               } else obj->minor=-1;
 
-               chips_p[chip]->msgobj[i]->flags = 0x0;
-       
-               candevices_p[card]->hwspecops->init_obj_data(chip,i);
+               candev->hwspecops->init_obj_data(hostchip,i);
 
                obj_count++;
        }
@@ -288,101 +333,106 @@ int init_obj_struct(int card, int chip)
 }
 
 
-int init_hwspecops(int card)
+int init_hwspecops(struct candevice_t *candev)
 {
        #ifdef ENABLE_CARD_template
-       if (!strcmp(candevices_p[card]->hwname,"template")) {
-               template_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"template")) {
+               template_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_pip
-       if (!strcmp(candevices_p[card]->hwname,"pip5")) {
-               pip5_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"pip5")) {
+               pip5_register(candev->hwspecops);
        }
-       else if (!strcmp(candevices_p[card]->hwname,"pip6")) {
-               pip6_register(candevices_p[card]->hwspecops);
+       else if (!strcmp(candev->hwname,"pip6")) {
+               pip6_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_smartcan
-       if (!strcmp(candevices_p[card]->hwname,"smartcan")) {
-               smartcan_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"smartcan")) {
+               smartcan_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_nsi
-       if (!strcmp(candevices_p[card]->hwname,"nsican")) {
-               nsi_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"nsican")) {
+               nsi_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_cc_can104
-       if (!strcmp(candevices_p[card]->hwname,"cc104")) {
-               cc104_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"cc104")) {
+               cc104_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_aim104
-       if (!strcmp(candevices_p[card]->hwname,"aim104")) {
-               aim104_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"aim104")) {
+               aim104_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_pc_i03
-       if (!strcmp(candevices_p[card]->hwname,"pc-i03")) {
-               pci03_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"pc-i03")) {
+               pci03_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_pcm3680
-       if (!strcmp(candevices_p[card]->hwname,"pcm3680")) {
-               pcm3680_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"pcm3680")) {
+               pcm3680_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_pccan
-       if (!strcmp(candevices_p[card]->hwname,"pccan-f") |
-                !strcmp(candevices_p[card]->hwname,"pccan-s") ) {
-               pccanf_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"pccan-f") |
+                !strcmp(candev->hwname,"pccan-s") ) {
+               pccanf_register(candev->hwspecops);
        }
-       if (!strcmp(candevices_p[card]->hwname,"pccan-d")) {
-               pccand_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"pccan-d")) {
+               pccand_register(candev->hwspecops);
        }
-       if (!strcmp(candevices_p[card]->hwname,"pccan-q")) {
-               pccanq_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"pccan-q")) {
+               pccanq_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_m437
-       if (!strcmp(candevices_p[card]->hwname,"m437")) {
-               m437_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"m437")) {
+               m437_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_pcccan
-       if (!strcmp(candevices_p[card]->hwname,"pcccan")) {
-               pcccan_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"pcccan")) {
+               pcccan_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_ssv
-       if (!strcmp(candevices_p[card]->hwname,"ssv")) {
-               ssv_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"ssv")) {
+               ssv_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_bfadcan
-       if (!strcmp(candevices_p[card]->hwname,"bfadcan")) {
-               bfadcan_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"bfadcan")) {
+               bfadcan_register(candev->hwspecops);
        }
        #endif
        #ifdef ENABLE_CARD_pikronisa
-       if (!strcmp(candevices_p[card]->hwname,"pikronisa")) {
-               pikronisa_register(candevices_p[card]->hwspecops);
+       if (!strcmp(candev->hwname,"pikronisa")) {
+               pikronisa_register(candev->hwspecops);
        }
        #endif
        return 0;
 }
 
-int init_chipspecops(int card, int chipnr)
+int init_chipspecops(struct candevice_t *candev, int chipnr)
 {
-       if (!strcmp(candevices_p[card]->chip[chipnr]->chip_type,"i82527")) {
-               i82527_register(candevices_p[card]->chip[chipnr]->chipspecops);
+       candev->chip[chipnr]->max_objects=0;
+       
+       if (!strcmp(candev->chip[chipnr]->chip_type,"i82527")) {
+               candev->chip[chipnr]->max_objects=15;
+               i82527_register(candev->chip[chipnr]->chipspecops);
        } 
-       if (!strcmp(candevices_p[card]->chip[chipnr]->chip_type,"sja1000")) {
-               sja1000_register(candevices_p[card]->chip[chipnr]->chipspecops);
+       if (!strcmp(candev->chip[chipnr]->chip_type,"sja1000")) {
+               candev->chip[chipnr]->max_objects=1;
+               sja1000_register(candev->chip[chipnr]->chipspecops);
        }
-       if (!strcmp(candevices_p[card]->chip[chipnr]->chip_type,"sja1000p")) {
-               sja1000p_register(candevices_p[card]->chip[chipnr]->chipspecops);
+       if (!strcmp(candev->chip[chipnr]->chip_type,"sja1000p")) {
+               candev->chip[chipnr]->max_objects=1;
+               sja1000p_register(candev->chip[chipnr]->chipspecops);
        }
 
        return 0;
index 0955c76..bca1fec 100644 (file)
@@ -1,25 +1,24 @@
 /* sja1000.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.6 18 Sept 2000
+ * 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
 
+#include <linux/sched.h>
 #include <linux/delay.h>
 #include <asm/irq.h>
 
 #include "../include/main.h"
 #include "../include/sja1000.h"
 
+void sja1000_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj);
+void sja1000_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj);
+
 int sja1000_enable_configuration(struct chip_t *chip)
 {
        int i=0;
@@ -194,48 +193,31 @@ int sja1000_baud_rate(struct chip_t *chip, int rate, int clock, int sjw,
 int sja1000_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
 {
        int i;
-       struct canfifo_t *fifo = chip->msgobj[0]->fifo;
-       int id;
+       
        i=can_read_reg(chip,SJASR);
        
        if (!(i&SR_RBS)) {
 //Temp
-       for (i=0; i<0x20; i++)
-               CANMSG("0x%x is 0x%x\n",i,can_read_reg(chip,i));
-               return 0;
+               for (i=0; i<0x20; i++)
+                       CANMSG("0x%x is 0x%x\n",i,can_read_reg(chip,i));
+                       return 0;
        }
        sja1000_start_chip(chip);
 
-       can_write_reg(chip, 0, SJACR); // disable interrupts for a moment
-// TODO: this would be best sja1000_irq_read_handler(chip);
-// now just duplicate the code.
-       do {
-               id = can_read_reg(chip, SJARXID0) | (can_read_reg(chip, SJARXID1)<<8);
-               fifo->rx_writep->length = id & 0x0f;
-               fifo->rx_writep->flags = id&ID0_RTR ? MSG_RTR : 0;
-               fifo->rx_writep->timestamp = 0;
-               fifo->rx_writep->cob = 0;
-               fifo->rx_writep->id = id>>5;
+    // disable interrupts for a moment
+       can_write_reg(chip, 0, SJACR); 
 
-               for (i=0; i<fifo->rx_writep->length; i++)
-                       fifo->rx_writep->data[i]=can_read_reg(chip, SJARXDAT0 + i);
+       sja1000_irq_read_handler(chip, obj);
 
-               fifo->rx_writep++;
-               if (fifo->rx_writep >= fifo->buf_rx_entry + MAX_BUF_LENGTH)
-                       fifo->rx_writep = fifo->buf_rx_entry;
-
-               can_write_reg(chip, CMR_RRB, SJACMR);
-
-       } while (can_read_reg(chip, SJASR) & SR_RBS);
-
-// enable interrupts
+    // enable interrupts
        can_write_reg(chip, CR_OIE | CR_EIE | CR_TIE | CR_RIE, SJACR);
 
 
        return 1;
 }
 
-#define MAX_TRANSMIT_WAIT_LOOPS 200
+#define MAX_TRANSMIT_WAIT_LOOPS 10
+
 int sja1000_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, 
                                                        struct canmsg_t *msg)
 {
@@ -349,6 +331,138 @@ int sja1000_config_irqs(struct chip_t *chip, short irqs)
        return -ENOSYS;
 }
 
+
+irqreturn_t sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       unsigned irq_register;
+       struct chip_t *chip=(struct chip_t *)dev_id;
+       struct msgobj_t *obj=chip->msgobj[0];
+
+       irq_register=can_read_reg(chip, SJAIR);
+//     DEBUGMSG("sja1000_irq_handler: SJAIR:%02x\n",irq_register);
+//     DEBUGMSG("sja1000_irq_handler: SJASR:%02x\n",
+//                                     can_read_reg(chip, SJASR));
+
+       if ((irq_register & (IR_WUI|IR_DOI|IR_EI|IR_TI|IR_RI)) == 0)
+               return IRQ_NONE;
+
+       if ((irq_register & IR_RI) != 0) 
+               sja1000_irq_read_handler(chip, obj);
+
+       if ((irq_register & IR_TI) != 0) { 
+               set_bit(OBJ_TX_REQUEST,&obj->flags);
+               while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){
+                       clear_bit(OBJ_TX_REQUEST,&obj->flags);
+
+                       if (can_read_reg(chip, SJASR) & SR_TBS)
+                               sja1000_irq_write_handler(chip, obj);
+
+                       clear_bit(OBJ_TX_LOCK,&obj->flags);
+                       if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break;
+               }
+       }
+
+       if ((irq_register & (IR_EI|IR_DOI)) != 0) { 
+               // Some error happened
+// FIXME: chip should be brought to usable state. Transmission cancelled if in progress.
+// Reset flag set to 0 if chip is already off the bus. Full state report
+               CANMSG("Error: status register: 0x%x irq_register: 0x%02x\n",
+                       can_read_reg(chip, SJASR), irq_register);
+               obj->ret=-1;
+
+               if(obj->tx_slot){
+                       canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_BUS);
+                       /*canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+                       obj->tx_slot=NULL;*/
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+void sja1000_irq_read_handler(struct chip_t *chip, struct msgobj_t *obj)
+{
+       int i=0, id=0;
+
+       do {
+               id = can_read_reg(chip, SJARXID0) | (can_read_reg(chip, SJARXID1)<<8);
+               obj->rx_msg.length = id & 0x0f;
+               obj->rx_msg.flags = id&ID0_RTR ? MSG_RTR : 0;
+               obj->rx_msg.timestamp = 0;
+               obj->rx_msg.cob = 0;
+               obj->rx_msg.id = id>>5;
+
+               for (i=0; i<obj->rx_msg.length; i++)
+                       obj->rx_msg.data[i]=can_read_reg(chip, SJARXDAT0 + i);
+
+               can_write_reg(chip, CMR_RRB, SJACMR);
+
+               canque_filter_msg2edges(obj->qends, &obj->rx_msg);
+       } while(can_read_reg(chip, SJASR) & SR_RBS);
+}
+
+void sja1000_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
+{
+       int cmd;
+       
+       if(obj->tx_slot){
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+       }
+
+       cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
+       if(cmd<0)
+               return;
+
+       if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
+               obj->ret = -1;
+               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+               return;
+       }
+       if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
+               obj->ret = -1;
+               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+               return;
+       }
+}
+
+/**
+ * sja1000_wakeup_tx: - wakeups TX processing
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000.c
+ */
+int sja1000_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj)
+{
+        /* dummy lock to prevent preemption fully portable way */
+       spinlock_t dummy_lock;
+       
+       /*  preempt_disable() */
+       spin_lock_init(&dummy_lock);
+       spin_lock(&dummy_lock);
+       
+       set_bit(OBJ_TX_REQUEST,&obj->flags);
+       while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){
+               clear_bit(OBJ_TX_REQUEST,&obj->flags);
+
+               if (can_read_reg(chip, SJASR) & SR_TBS)
+                       sja1000_irq_write_handler(chip, obj);
+       
+               clear_bit(OBJ_TX_LOCK,&obj->flags);
+               if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break;
+       }
+
+       /* preempt_enable(); */
+       spin_unlock(&dummy_lock);
+       return 0;
+}
+
 int sja1000_register(struct chipspecops_t *chipspecops)
 {
        chipspecops->chip_config = sja1000_chip_config;
@@ -362,6 +476,7 @@ int sja1000_register(struct chipspecops_t *chipspecops)
        chipspecops->pre_write_config = sja1000_pre_write_config;
        chipspecops->send_msg = sja1000_send_msg;
        chipspecops->check_tx_stat = sja1000_check_tx_stat;
+       chipspecops->wakeup_tx=sja1000_wakeup_tx;
        chipspecops->remote_request = sja1000_remote_request;
        chipspecops->enable_configuration = sja1000_enable_configuration;
        chipspecops->disable_configuration = sja1000_disable_configuration;
index deb1c89..19e2e57 100644 (file)
@@ -1,20 +1,15 @@
 /* sja1000.c
  * Linux CAN-bus device driver.
  * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
- * This software is released under the GPL-License.
- * Version 0.6 18 Sept 2000
  * Changed for PeliCan mode SJA1000 by Tomasz Motylewski (BFAD GmbH)
  * T.Motylewski@bfad.de
+ * 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.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
 
 #include <linux/sched.h>
 #include <linux/delay.h>
@@ -75,6 +70,18 @@ int sja1000p_disable_configuration(struct chip_t *chip)
        return 0;
 }
 
+/**
+ * sja1000p_chip_config: - can chip configuration
+ * @chip: pointer to chip state structure
+ *
+ * This function configures chip and prepares it for message
+ * transmission and reception. The function resets chip,
+ * resets mask for acceptance of all messages by call to
+ * sja1000p_extended_mask() function and then 
+ * computes and sets baudrate with use of function sja1000p_baud_rate().
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_chip_config(struct chip_t *chip)
 {
        if (sja1000p_enable_configuration(chip))
@@ -101,6 +108,15 @@ int sja1000p_chip_config(struct chip_t *chip)
        return 0;
 }
 
+/**
+ * sja1000p_extended_mask: - setup of extended mask for message filtering
+ * @chip: pointer to chip state structure
+ * @code: can message acceptance code
+ * @mask: can message acceptance mask
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_extended_mask(struct chip_t *chip, unsigned long code, unsigned  long mask)
 {
        int i;
@@ -124,12 +140,17 @@ int sja1000p_extended_mask(struct chip_t *chip, unsigned long code, unsigned  lo
        return 0;
 }
 
-/* Set communication parameters.
- * param rate baud rate in Hz
- * param clock frequency of sja1000 clock in Hz (ISA osc is 14318000)
- * param sjw synchronization jump width (0-3) prescaled clock cycles
- * param sampl_pt sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio
- * param flags fields BTR1_SAM, OCMODE, OCPOL, OCTP, OCTN, CLK_OFF, CBP
+/**
+ * sja1000p_baud_rate: - set communication parameters.
+ * @chip: pointer to chip state structure
+ * @rate: baud rate in Hz
+ * @clock: frequency of sja1000 clock in Hz (ISA osc is 14318000)
+ * @sjw: synchronization jump width (0-3) prescaled clock cycles
+ * @sampl_pt: sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio
+ * @flags: fields %BTR1_SAM, %OCMODE, %OCPOL, %OCTP, %OCTN, %CLK_OFF, %CBP
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
  */
 int sja1000p_baud_rate(struct chip_t *chip, int rate, int clock, int sjw,
                                                        int sampl_pt, int flags)
@@ -191,42 +212,55 @@ int sja1000p_baud_rate(struct chip_t *chip, int rate, int clock, int sjw,
        return 0;
 }
 
-void sja1000p_read(struct chip_t *chip, struct canfifo_t *fifo) {
+/**
+ * sja1000p_read: - reads and distributes one or more received messages
+ * @chip: pointer to chip state structure
+ * @obj: pinter to CAN message queue information
+ *
+ * File: src/sja1000p.c
+ */
+void sja1000p_read(struct chip_t *chip, struct msgobj_t *obj) {
        int i, flags, len, datastart;
        do {
                flags = can_read_reg(chip,SJAFRM);
                if(flags&FRM_FF) {
-                       fifo->rx_writep->id =
+                       obj->rx_msg.id =
                                (can_read_reg(chip,SJAID0)<<21) +
                                (can_read_reg(chip,SJAID1)<<13) +
                                (can_read_reg(chip,SJAID2)<<5) +
                                (can_read_reg(chip,SJAID3)>>3);
                        datastart = SJADATE;
                } else {
-                       fifo->rx_writep->id =
+                       obj->rx_msg.id =
                                (can_read_reg(chip,SJAID0)<<3) +
                                (can_read_reg(chip,SJAID1)>>5);
                        datastart = SJADATS;
                }
-               fifo->rx_writep->flags =
+               obj->rx_msg.flags =
                        ((flags & FRM_RTR) ? MSG_RTR : 0) |
                        ((flags & FRM_FF) ? MSG_EXT : 0);
                len = flags & FRM_DLC_M;
                for(i=0; i< len; i++) {
-                       fifo->rx_writep->data[i]=can_read_reg(chip,datastart+i);
+                       obj->rx_msg.data[i]=can_read_reg(chip,datastart+i);
                }
-               fifo->rx_writep->length = len;
+               obj->rx_msg.length = len;
 
-               fifo->rx_writep++;
-               if (fifo->rx_writep >= fifo->buf_rx_entry + MAX_BUF_LENGTH)
-                       fifo->rx_writep = fifo->buf_rx_entry;
-
-// FIXME: what if fifo->rx_writep == fifo->rx_readp again ?
+               canque_filter_msg2edges(obj->qends, &obj->rx_msg);
 
                can_write_reg(chip, CMR_RRB, SJACMR);
+
        } while (can_read_reg(chip, SJASR) & SR_RBS);
 }
 
+/**
+ * sja1000p_pre_read_config: - prepares message object for message reception
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ *
+ * Return Value: negative value reports error.
+ *     Positive value indicates immediate reception of message.
+ * File: src/sja1000p.c
+ */
 int sja1000p_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
 {
        int status;
@@ -247,12 +281,25 @@ int sja1000p_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
        }
 
        can_write_reg(chip, DISABLE_INTERRUPTS, SJAIER); //disable interrupts for a moment
-       sja1000p_read(chip, obj->fifo);
+       sja1000p_read(chip, obj);
        can_write_reg(chip, ENABLE_INTERRUPTS, SJAIER); //enable interrupts
        return 1;
 }
 
-#define MAX_TRANSMIT_WAIT_LOOPS 200
+#define MAX_TRANSMIT_WAIT_LOOPS 10
+/**
+ * sja1000p_pre_write_config: - prepares message object for message transmission
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ * @msg: pointer to CAN message
+ *
+ * This function prepares selected message object for future initiation
+ * of message transmission by sja1000p_send_msg() function.
+ * The CAN message data and message ID are transfered from @msg slot
+ * into chip buffer in this function.
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, 
                                                        struct canmsg_t *msg)
 {
@@ -319,6 +366,17 @@ int sja1000p_pre_write_config(struct chip_t *chip, struct msgobj_t *obj,
        return 0;
 }
 
+/**
+ * sja1000p_send_msg: - initiate message transmission
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object state structure
+ * @msg: pointer to CAN message
+ *
+ * This function is called after sja1000p_pre_write_config() function,
+ * which prepares data in chip buffer.
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_send_msg(struct chip_t *chip, struct msgobj_t *obj, 
                                                        struct canmsg_t *msg)
 {
@@ -327,6 +385,15 @@ int sja1000p_send_msg(struct chip_t *chip, struct msgobj_t *obj,
        return 0;
 }
 
+/**
+ * sja1000p_check_tx_stat: - checks state of transmission engine
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ *     Positive return value indicates transmission under way status.
+ *     Zero value indicates finishing of all issued transmission requests.
+ * File: src/sja1000p.c
+ */
 int sja1000p_check_tx_stat(struct chip_t *chip)
 {
        if (can_read_reg(chip,SJASR) & SR_TCS)
@@ -335,6 +402,15 @@ int sja1000p_check_tx_stat(struct chip_t *chip)
                return 1;
 }
 
+/**
+ * sja1000p_set_btregs: -  configures bitrate registers
+ * @chip: pointer to chip state structure
+ * @btr0: bitrate register 0
+ * @btr1: bitrate register 1
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_set_btregs(struct chip_t *chip, unsigned short btr0, 
                                                        unsigned short btr1)
 {
@@ -349,6 +425,13 @@ int sja1000p_set_btregs(struct chip_t *chip, unsigned short btr0,
        return 0;
 }
 
+/**
+ * sja1000p_stop_chip: -  starts chip message processing
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_start_chip(struct chip_t *chip)
 {
        enum sja1000_PeliCAN_MOD flags;
@@ -359,6 +442,13 @@ int sja1000p_start_chip(struct chip_t *chip)
        return 0;
 }
 
+/**
+ * sja1000p_stop_chip: -  stops chip message processing
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_stop_chip(struct chip_t *chip)
 {
        enum sja1000_PeliCAN_MOD flags;
@@ -370,12 +460,29 @@ int sja1000p_stop_chip(struct chip_t *chip)
 }
 
 
+/**
+ * sja1000p_remote_request: - configures message object and asks for RTR message
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_remote_request(struct chip_t *chip, struct msgobj_t *obj)
 {
        CANMSG("sja1000p_remote_request not implemented\n");
        return -ENOSYS;
 }
 
+/**
+ * sja1000p_standard_mask: - setup of mask for message filtering
+ * @chip: pointer to chip state structure
+ * @code: can message acceptance code
+ * @mask: can message acceptance mask
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_standard_mask(struct chip_t *chip, unsigned short code,
                unsigned short mask)
 {
@@ -383,58 +490,97 @@ int sja1000p_standard_mask(struct chip_t *chip, unsigned short code,
        return -ENOSYS;
 }
 
+/**
+ * sja1000p_clear_objects: - clears state of all message object residing in chip
+ * @chip: pointer to chip state structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_clear_objects(struct chip_t *chip)
 {
        CANMSG("sja1000p_clear_objects not implemented\n");
        return -ENOSYS;
 }
 
+/**
+ * sja1000p_config_irqs: - tunes chip hardware interrupt delivery
+ * @chip: pointer to chip state structure
+ * @irqs: requested chip IRQ configuration
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
 int sja1000p_config_irqs(struct chip_t *chip, short irqs)
 {
        CANMSG("sja1000p_config_irqs not implemented\n");
        return -ENOSYS;
 }
 
-void sja1000p_irq_write_handler(struct chip_t *chip, struct canfifo_t *fifo)
+/**
+ * sja1000p_irq_write_handler: - part of ISR code responsible for transmit events
+ * @chip: pointer to chip state structure
+ * @obj: pointer to attached queue description
+ *
+ * The main purpose of this function is to read message from attached queues
+ * and transfer message contents into CAN controller chip.
+ * This subroutine is called by
+ * sja1000p_irq_write_handler() for transmit events.
+ * File: src/sja1000p.c
+ */
+void sja1000p_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj)
 {
-       fifo->tx_readp++;
-       if (fifo->tx_readp >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
-               fifo->tx_readp = fifo->buf_tx_entry;
-       if (fifo->tx_readp == fifo->tx_writep) { // Output buffer is empty
-               fifo->tx_in_progress = 0;
-               if (waitqueue_active(&fifo->writeq)) {
-                       chip->msgobj[0]->ret = 0; //CHECKME or 26?
-                       wake_up_interruptible(&fifo->writeq);
-               }
-               return;
+       int cmd;
+       
+       if(obj->tx_slot){
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
        }
-       if (chip->chipspecops->pre_write_config(chip, chip->msgobj[0],
-                               fifo->tx_readp)) {
-               if (waitqueue_active(&fifo->writeq)) {
-                       chip->msgobj[0]->ret = -1;
-                       wake_up_interruptible(&fifo->writeq);
-                       return;
-               }
+       
+       cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
+       if(cmd<0)
+               return;
+
+       if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
+               obj->ret = -1;
+               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+               return;
        }
-       if (chip->chipspecops->send_msg(chip, chip->msgobj[0],
-               fifo->tx_readp)) {
-               if (waitqueue_active(&fifo->writeq)) {
-                       chip->msgobj[0]->ret = -1;
-                       wake_up_interruptible(&fifo->writeq);
-                       return;
-               }
+       if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
+               obj->ret = -1;
+               canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
+               canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+               obj->tx_slot=NULL;
+               return;
        }
 
 }
 
 #define MAX_RETR 10
 
-void sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+/**
+ * sja1000p_irq_handler: - interrupt service routine
+ * @irq: interrupt vector number, this value is system specific
+ * @dev_id: driver private pointer registered at time of request_irq() call.
+ *     The CAN driver uses this pointer to store relationship of interrupt
+ *     to chip state structure - @struct chip_t
+ * @regs: system dependent value pointing to registers stored in exception frame
+ * 
+ * Interrupt handler is activated when state of CAN controller chip changes,
+ * there is message to be read or there is more space for new messages or
+ * error occurs. The receive events results in reading of the message from
+ * CAN controller chip and distribution of message through attached
+ * message queues.
+ * File: src/sja1000p.c
+ */
+irqreturn_t sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
        int irq_register, status, error_code;
        int static retransmitted=0; /* FIXME - should go into chip struct */
        struct chip_t *chip=(struct chip_t *)dev_id;
-       struct canfifo_t *fifo;
+       struct msgobj_t *obj=chip->msgobj[0];
 
        irq_register=can_read_reg(chip,SJAIR);
 //     DEBUGMSG("sja1000_irq_handler: SJAIR:%02x\n",irq_register);
@@ -442,23 +588,32 @@ void sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 //                                     can_read_reg(chip,SJASR));
 
        if ((irq_register & (IR_BEI|IR_EPI|IR_DOI|IR_EI|IR_TI|IR_RI)) == 0)
-               return;
+               return IRQ_NONE;
 
-       if(!chip->msgobj[0]->flags & BUFFERS_ALLOCATED) {
+       if(!obj->flags & OBJ_BUFFERS_ALLOCATED) {
                CANMSG("sja1000p_irq_handler: called with device closed, irq_register 0x%02x\n", irq_register);
-               return;
+               return IRQ_NONE;
        }
-       fifo=chip->msgobj[0]->fifo;
 
        if ((irq_register & IR_RI) != 0) {
-               sja1000p_read(chip,fifo);
-               chip->msgobj[0]->ret = 0;
-               if (waitqueue_active(&fifo->readq))
-                       wake_up_interruptible(&fifo->readq);
+               DEBUGMSG("sja1000_irq_handler: RI\n");
+               sja1000p_read(chip,obj);
+               obj->ret = 0;
        }
        if ((irq_register & IR_TI) != 0) {
-               chip->msgobj[0]->ret = 0;
-               sja1000p_irq_write_handler(chip,fifo);
+               DEBUGMSG("sja1000_irq_handler: TI\n");
+               obj->ret = 0;
+               set_bit(OBJ_TX_REQUEST,&obj->flags);
+               while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){
+                       clear_bit(OBJ_TX_REQUEST,&obj->flags);
+
+                       if (can_read_reg(chip, SJASR) & SR_TBS)
+                               sja1000p_irq_write_handler(chip, obj);
+
+                       clear_bit(OBJ_TX_LOCK,&obj->flags);
+                       if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break;
+                       DEBUGMSG("TX looping in sja1000_irq_handler\n");
+               }
        }
        if ((irq_register & (IR_EI|IR_BEI|IR_EPI|IR_DOI)) != 0) { 
                // Some error happened
@@ -468,10 +623,10 @@ void sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
                        status, irq_register, error_code);
 // FIXME: chip should be brought to usable state. Transmission cancelled if in progress.
 // Reset flag set to 0 if chip is already off the bus. Full state report
-               chip->msgobj[0]->ret=-1;
+               obj->ret=-1;
                
                if(error_code == 0xd9) {
-                       chip->msgobj[0]->ret= -ENXIO;
+                       obj->ret= -ENXIO;
                        /* no such device or address - no ACK received */
                }
                if(retransmitted++>MAX_RETR) {
@@ -483,15 +638,51 @@ void sja1000p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
                        can_write_reg(chip, 0, SJAMOD);
                }
                
-               if (waitqueue_active(&fifo->writeq))
-                       wake_up_interruptible(&fifo->writeq);
-               if (waitqueue_active(&fifo->readq))
-                       wake_up_interruptible(&fifo->readq);
+               if(obj->tx_slot){
+                       canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_BUS);
+                       /*canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+                       obj->tx_slot=NULL;*/
+               }
+
        } else {
                retransmitted=0;
        }
 
-       return;
+       return IRQ_HANDLED;
+}
+
+/**
+ * sja1000p_wakeup_tx: - wakeups TX processing
+ * @chip: pointer to chip state structure
+ * @obj: pointer to message object structure
+ *
+ * Return Value: negative value reports error.
+ * File: src/sja1000p.c
+ */
+int sja1000p_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj)
+{
+        /* dummy lock to prevent preemption fully portable way */
+       spinlock_t dummy_lock;
+       
+       /*  preempt_disable() */
+       spin_lock_init(&dummy_lock);
+       spin_lock(&dummy_lock);
+       
+       set_bit(OBJ_TX_REQUEST,&obj->flags);
+       while(!test_and_set_bit(OBJ_TX_LOCK,&obj->flags)){
+               clear_bit(OBJ_TX_REQUEST,&obj->flags);
+
+               if (can_read_reg(chip, SJASR) & SR_TBS)
+                       sja1000p_irq_write_handler(chip, obj);
+       
+               clear_bit(OBJ_TX_LOCK,&obj->flags);
+               if(!test_bit(OBJ_TX_REQUEST,&obj->flags)) break;
+               DEBUGMSG("TX looping in sja1000p_wakeup_tx\n");
+       }
+
+       /* preempt_enable(); */
+       spin_unlock(&dummy_lock);
+       return 0;
 }
 
 int sja1000p_register(struct chipspecops_t *chipspecops)
@@ -508,6 +699,7 @@ int sja1000p_register(struct chipspecops_t *chipspecops)
        chipspecops->pre_write_config=sja1000p_pre_write_config;
        chipspecops->send_msg=sja1000p_send_msg;
        chipspecops->check_tx_stat=sja1000p_check_tx_stat;
+       chipspecops->wakeup_tx=sja1000p_wakeup_tx;
        chipspecops->remote_request=sja1000p_remote_request;
        chipspecops->enable_configuration=sja1000p_enable_configuration;
        chipspecops->disable_configuration=sja1000p_disable_configuration;
index c41c2d6..731f657 100644 (file)
@@ -1,18 +1,13 @@
 /* smartcan.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
 
 #include <linux/ioport.h>
 #include <linux/delay.h>
 int smartcan_irq=-1;
 unsigned long smartcan_base=0x0;
 
-int smartcan_request_io(unsigned long io_addr)
+int smartcan_request_io(struct candevice_t *candev)
 {
-       int err=0;
-
-       if ( (err=check_region(io_addr,0x04)) < 0 ) {
-               CANMSG("Unable to open port: 0x%lx\n",io_addr);
+       if (!can_request_io_region(candev->io_addr,0x04,DEVICE_NAME)) {
+               CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
                return -ENODEV;
-       }
-       else {
-               request_region(io_addr,0x04,DEVICE_NAME);
-               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + 0x04 - 1);
+       }else {
+               DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + 0x04 - 1);
        }
        return 0;
 }
 
-int smartcan_release_io(unsigned long io_addr)
+int smartcan_release_io(struct candevice_t *candev)
 {
-       release_region(io_addr,0x04);
+       can_release_io_region(candev->io_addr,0x04);
 
        return 0;
 }
 
-int smartcan_reset(int card)
+int smartcan_reset(struct candevice_t *candev)
 {
        int i=0;
 
        DEBUGMSG("Resetting smartcan hardware ...\n");
-       outb(0x00,candevices_p[card]->res_addr);
+       outb(0x00,candev->res_addr);
        while (i < 1000000) {
                i++;
-               outb(0x01,candevices_p[card]->res_addr);
+               outb(0x01,candev->res_addr);
        }
-       outb(0x00,candevices_p[card]->res_addr); 
+       outb(0x00,candev->res_addr); 
 
        /* Check hardware reset status */
        i=0;
-       outb(candevices_p[card]->io_addr+iCPU,candevices_p[card]->io_addr);
-       while ( (inb(candevices_p[card]->io_addr+1)&0x80) && (i<=15) ) {
+       outb(candev->io_addr+iCPU,candev->io_addr);
+       while ( (inb(candev->io_addr+1)&0x80) && (i<=15) ) {
                udelay(20000);
                i++;
        }
@@ -80,35 +71,36 @@ int smartcan_reset(int card)
        return 0;
 } 
 
-int smartcan_init_hw_data(int card)
+int smartcan_init_hw_data(struct candevice_t *candev)
 {
-       candevices_p[card]->res_addr=candevices_p[card]->io_addr+0x02;
-       candevices_p[card]->nr_82527_chips=1;
-       candevices_p[card]->nr_sja1000_chips=0;
-
+       candev->res_addr=candev->io_addr+0x02;
+       candev->nr_82527_chips=1;
+       candev->nr_sja1000_chips=0;
+       candev->nr_all_chips=1;
+       
        return 0;
 }
 
-int smartcan_init_chip_data(int card, int chipnr)
+int smartcan_init_chip_data(struct candevice_t *candev, int chipnr)
 {
-       candevices_p[card]->chip[chipnr]->chip_type="i82527";
-       candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
-       candevices_p[card]->chip[chipnr]->clock = 16000000;
-       candevices_p[card]->chip[chipnr]->int_cpu_reg = iCPU_DSC;
-       candevices_p[card]->chip[chipnr]->int_clk_reg = iCLK_SL1;
-       candevices_p[card]->chip[chipnr]->int_bus_reg = iBUS_CBY;
-       candevices_p[card]->chip[chipnr]->sja_cdr_reg = 0;
-       candevices_p[card]->chip[chipnr]->sja_ocr_reg = 0;
-       smartcan_irq=candevices_p[card]->chip[chipnr]->chip_irq;
-       smartcan_base=candevices_p[card]->chip[chipnr]->chip_base_addr;
+       candev->chip[chipnr]->chip_type="i82527";
+       candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+       candev->chip[chipnr]->clock = 16000000;
+       candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
+       candev->chip[chipnr]->int_clk_reg = iCLK_SL1;