* Version lincan-0.2 9 Jul 2003
*/
-#include <asm/io.h>
-#include <linux/fs.h>
-#include <linux/version.h>
-#include <linux/wait.h>
-#include <linux/interrupt.h>
#include "./can.h"
#include "./constants.h"
+#include "./can_sysdep.h"
#include "./can_queue.h"
+#include "lincan_config.h"
#ifdef CAN_DEBUG
- #define DEBUGMSG(fmt,args...) printk(KERN_ERR "can.o (debug): " fmt,\
+ #define DEBUGMSG(fmt,args...) can_printk(KERN_ERR "can.o (debug): " fmt,\
##args)
#else
#define DEBUGMSG(fmt,args...)
#endif
-#define CANMSG(fmt,args...) printk(KERN_ERR "can.o: " fmt,##args)
+#define CANMSG(fmt,args...) can_printk(KERN_ERR "can.o: " fmt,##args)
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,7))
-#define MINOR_NR \
- (MINOR(file->f_dentry->d_inode->i_rdev))
-
-#else /* Linux kernel > 2.5.7 */
-
-#define MINOR_NR \
- (minor(file->f_dentry->d_inode->i_rdev))
-#endif /* Linux kernel > 2.5.7 */
-
-#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 */
+extern can_spinlock_t canuser_manipulation_lock;
/**
* struct canhardware_t - structure representing pointers to all CAN boards
struct canhardware_t {
int nr_boards;
struct rtr_id *rtr_queue;
- spinlock_t rtr_lock;
+ can_spinlock_t rtr_lock;
struct candevice_t *candevice[MAX_HW_CARDS];
};
* @chip: array of pointers to the chip structures
* @hwspecops: pointer to board specific operations
* @hosthardware_p: pointer to the root hardware structure
+ * @sysdevptr: union reserved for pointer to bus specific
+ * device structure (case @pcidev is used for PCI devices)
*
* The structure represent configuration and state of associated board.
* The driver infrastructure prepares this structure and calls
struct hwspecops_t *hwspecops;
struct canhardware_t *hosthardware_p;
+
+ union {
+ #ifdef CAN_ENABLE_PCI_SUPPORT
+ struct pci_dev *pcidev;
+ #endif /*CAN_ENABLE_PCI_SUPPORT*/
+ } sysdevptr;
+
};
/**
* @flags: chip flags: %CHIP_CONFIGURED .. chip is configured,
* %CHIP_SEGMENTED .. access to the chip is segmented (mainly for i82527 chips)
* @clock: chip base clock frequency in Hz
+ * @baudrate: selected chip baudrate in Hz
* @write_register: write chip register function copy -
* @read_register: read chip register function copy
* @sja_cdr_reg: SJA specific register -
* @chipspecops: pointer to the set of chip specific object filled by init_chip_data() function
* @hostdevice: pointer to chip hosting board
* @max_objects: maximal number of communication objects connected to this chip
+ * @chip_lock: reserved for synchronization of the chip supporting routines
+ * (not used in the current driver version)
+ * @worker_thread: chip worker thread ID (RT-Linux specific field)
+ * @pend_flags: holds information about pending interrupt and tx_wake() operations
+ * (RT-Linux specific field). Masks values:
+ * %MSGOBJ_TX_REQUEST .. some of the message objects requires tx_wake() call,
+ * %MSGOBJ_IRQ_REQUEST .. chip interrupt processing required
+ * %MSGOBJ_WORKER_WAKE .. marks, that worker thread should be waked
+ * for some of above reasons
*
* The fields @write_register and @read_register are copied from
* corresponding fields from @hwspecops structure
int chip_irq;
unsigned long chip_base_addr;
unsigned int flags;
- int clock; /* Chip clock in Hz */
+ long clock; /* Chip clock in Hz */
+ long baudrate;
void (*write_register)(unsigned char data,unsigned long address);
unsigned (*read_register)(unsigned long address);
struct candevice_t *hostdevice;
- int max_objects; /* 1 for sja1000, 15 for */
+ int max_objects; /* 1 for sja1000, 15 for i82527 */
+
+ can_spinlock_t chip_lock;
+
+ #ifdef CAN_WITH_RTL
+ pthread_t worker_thread;
+ unsigned long pend_flags;
+ #endif /*CAN_WITH_RTL*/
};
/**
* canque_test_outslot() call and is freed by canque_free_outslot()
* or rescheduled canque_again_outslot()
* @tx_retry_cnt: transmission attempt counter
+ * @tx_timeout: can be used by chip driver to check for the transmission timeout
* @rx_msg: temporary storage to hold received messages before
* calling to canque_filter_msg2edges()
* @hostchip: pointer to the &chip_t structure this object belongs to
* @obj_used: counter of users (associated file structures for Linux
* userspace clients) of this object
* @obj_users: list of user structures of type &canuser_t.
+ * @obj_flags: message object specific flags. Masks values:
+ * %MSGOBJ_TX_REQUEST .. the message object requests TX activation
+ * %MSGOBJ_TX_LOCK .. some IRQ routine or callback on some CPU
+ * is running inside TX activation processing code
*/
struct msgobj_t {
unsigned long obj_base_addr;
unsigned int minor; /* associated device minor number */
unsigned int object; /* object number in chip_t +1 for debug printk */
- unsigned long flags;
+ unsigned long obj_flags;
int ret;
struct canque_ends_t *qends;
struct canque_edge_t *tx_qedge;
struct canque_slot_t *tx_slot;
int tx_retry_cnt;
+ struct timer_list tx_timeout;
struct canmsg_t rx_msg;
/**
* struct canuser_t - structure holding CAN user/client state
+ * @flags: used to distinguish Linux/RT-Linux type
* @peers: for connection into list of object users
* @qends: pointer to the ends structure corresponding for this user
- * @file: pointer to open device file state structure
* @msgobj: communication object the user is connected to
* @rx_edge0: default receive queue for filter IOCTL
+ * @userinfo: stores user context specific information.
+ * The field @fileinfo.file holds pointer to open device file state structure
+ * for the Linux user-space client applications
* @magic: magic number to check consistency when pointer is retrieved
* from file private field
*/
struct canuser_t {
+ unsigned long flags;
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 */
+ union {
+ struct {
+ struct file *file; /* back ptr to file */
+ } fileinfo;
+ #ifdef CAN_WITH_RTL
+ struct {
+ struct rtl_file *file;
+ } rtlinfo;
+ #endif /*CAN_WITH_RTL*/
+ } userinfo;
int magic;
};
* @remote_request: configures message object and asks for RTR message
* @check_tx_stat: checks state of transmission engine
* @wakeup_tx: wakeup TX processing
+ * @filtch_rq: optional routine for propagation of outgoing edges filters to HW
* @enable_configuration: enable chip configuration mode
* @disable_configuration: disable chip configuration mode
* @set_btregs: configures bitrate registers
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 (*filtch_rq)(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);
- irqreturn_t (*irq_handler)(int irq, void *dev_id, struct pt_regs *regs);
+ can_irqreturn_t (*irq_handler)(int irq, void *dev_id, struct pt_regs *regs);
};
struct mem_addr {
void *address;
struct mem_addr *next;
+ size_t size;
};
/* Structure for the RTR queue */
extern int major;
extern int minor[MAX_TOT_CHIPS];
extern int extended;
-extern int baudrate;
+extern int baudrate[MAX_TOT_CHIPS];
extern char *hw[MAX_HW_CARDS];
extern int irq[MAX_IRQ];
extern unsigned long io[MAX_HW_CARDS];
extern struct mem_addr *mem_head;
+
+#if defined(CONFIG_OC_LINCAN_PORTIO_ONLY)
+extern inline void can_write_reg(const struct chip_t *chip, unsigned char data, unsigned address)
+{
+ outb(data, chip->chip_base_addr+address);
+}
+extern inline unsigned can_read_reg(const struct chip_t *chip, unsigned address)
+{
+ return inb(chip->chip_base_addr+address);
+}
+extern inline void canobj_write_reg(const struct chip_t *chip, const struct msgobj_t *obj,
+ unsigned char data, unsigned address)
+{
+ outb(data, obj->obj_base_addr+address);
+}
+extern inline unsigned canobj_read_reg(const struct chip_t *chip, const struct msgobj_t *obj,
+ unsigned address)
+{
+ return inb(obj->obj_base_addr+address);
+}
+
+#elif defined(CONFIG_OC_LINCAN_MEMIO_ONLY)
+extern inline void can_write_reg(const struct chip_t *chip, unsigned char data, unsigned address)
+{
+ writeb(data, chip->chip_base_addr+address);
+}
+extern inline unsigned can_read_reg(const struct chip_t *chip, unsigned address)
+{
+ return readb(chip->chip_base_addr+address);
+}
+extern inline void canobj_write_reg(const struct chip_t *chip, const struct msgobj_t *obj,
+ unsigned char data, unsigned address)
+{
+ writeb(data, obj->obj_base_addr+address);
+}
+extern inline unsigned canobj_read_reg(const struct chip_t *chip, const struct msgobj_t *obj,
+ unsigned address)
+{
+ return readb(obj->obj_base_addr+address);
+}
+
+#else /*CONFIG_OC_LINCAN_DYNAMICIO*/
+#ifndef CONFIG_OC_LINCAN_DYNAMICIO
+#define CONFIG_OC_LINCAN_DYNAMICIO
+#endif
+
/* 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.
*/
return chip->read_register(address_to_read);
}
+#endif /*CONFIG_OC_LINCAN_DYNAMICIO*/
+
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);
};
const struct boardtype_t* boardtype_find(const char *str);
+
+#ifdef CAN_WITH_RTL
+extern int can_rtl_priority;
+#endif /*CAN_WITH_RTL*/