The latest version of stand-alone LinCAN sources can be
obtained from GIT repository and build by next commands
- git clone git://ortcan.git.sourceforge.net/gitroot/ortcan/lincan
+ git clone git://git.code.sf.net/p/ortcan/lincan
cd lincan
./build-lincan.sh
The other option is to build LinCAN driver as part of the whole
OrtCAN tree
- git clone git://ortcan.git.sourceforge.net/gitroot/ortcan/ortcan
+ git clone git://git.code.sf.net/p/ortcan/ortcan-top
cd ortcan/
git submodule update --init
make default-config
============
Type 'make install' for standard make system compilation.
The driver should be copied into actual kernel version
-modules directory "/lib/modules/x.y.z/kernel/drivers/char".
+modules directory "/lib/modules/x.y.z/extra".
OMK system requires manual copy of files from "_compiled" tree
-to its final destinations.
+to its final destinations. Just compiled driver can be
+tested directly from LinCAN build directory (i.e. example
+for PC/104 PCM3680 board)
-Create file "lincan.rules" with contents listed below in or linked
-into "/etc/udev/rules.d" directory to enable automatic device nodes
-creation for UDEV based system
+ insmod _compiled/modules/lincan.ko hw=pcm3680 io=0x200 irq=7,11
+
+Driver can be copied into system final location after testing
+
+ mkdir /lib/modules/$(uname -r)/extra
+ cp _compiled/modules/lincan.ko /lib/modules/$(uname -r)/extra
+ chown root:root /lib/modules/$(uname -r)/extra/lincan.ko
+ depmod -a
+
+Right to access the driver for non-root users can be granted by
+generation of "10-lincan.rules" in the UDEV configuration directory
+"/etc/udev/rules.d"
# LinCAN driver
SUBSYSTEM=="can",GROUP="users",MODE="0660"
-The driver automatic loding can be requested by addition of "lincan"
-line into "/etc/modules" od Debian based systems.
+The driver automatic loading of the driver can be requested by addition
+of "lincan" line into "/etc/modules" for Debian based systems. The module
+parameters can be specified in the same file after "lincan" driver name
+or in separate file in "/etc/modprobe.d" directory (i.e.)
+
+ echo >/etc/modprobe.d/lincan.conf \
+ options lincan processlocal=2 hw=pcm3680 io=0x200 irq=7,11
-The target hardware/board specific options should be added into
-"/etc/modprobe.conf" file or file with similar functionality for your
-distribution. The options are discusses in the next paragraph.
+This files location can vary between distributions.
+The LinCAN driver options are discusses in more details in
+the next paragraph.
LOADING
=======
- gensja1000io for many sja1000 I/O mapped cards (PCAN-PC/104 for example).
- gensja1000mm for ISA memory mapped sja1000 CAN cards
(for pikronisa card used by PiKRON Ltd. the clockfreq=24000 has to be specified)
+- pcisja1000mm for SJA1000 directly mapped into PCI mem region 0
- pimx1 for MX1_DIS1 extension board for PiMX1 ARM based BCC
- msmcan for MICROSPACE IO space indexed i82527
- unican for Unicontrols PCAN card
lincan_cards_NAMES = pip pccan smartcan nsi cc_can104 ems_cpcpci \
- pc_i03 pcm3680 aim104 m437 pcccan ssv bfadcan gensja1000io gensja1000mm eb8245 \
+ pc_i03 pcm3680 aim104 m437 pcccan ssv bfadcan gensja1000io gensja1000mm pcisja1000mm eb8245 \
kv_pcican msmcan oscar adlink7841 pcan_pci esdpci200 unican usbcan virtual template
lincan_morecards_NAMES = esdpci266 hms30c7202_can ns_dev_can ipci165 pimx1 tscan1 ts7kv nsi_canpci sh7760 mpc5200
SUPPORTED_CARDS = pip pccan smartcan nsi cc_can104 \
pc_i03 pcm3680 aim104 m437 pcccan ssv \
- bfadcan gensja1000mm gensja1000io kv_pcican msmcan virtual template \
+ bfadcan gensja1000mm gensja1000io pcisja1000mm \
+ kv_pcican msmcan virtual template \
unican unican_cl2 ems_cpcpci adlink7841 oscar \
pcan_pci esdpci200
# hms30c7202_can c_can c_can_irq tscan1
extern int bfadcan_register(struct hwspecops_t *hwspecops);
extern int gensja1000mm_register(struct hwspecops_t *hwspecops);
extern int gensja1000io_register(struct hwspecops_t *hwspecops);
+extern int pcisja1000mm_register(struct hwspecops_t *hwspecops);
extern int pimx1_register(struct hwspecops_t *hwspecops);
extern int msmcan_register(struct hwspecops_t *hwspecops);
extern int unican_register(struct hwspecops_t *hwspecops);
#ifdef CONFIG_OC_LINCAN_CARD_gensja1000io
{"gensja1000io", gensja1000io_register, 1},
#endif
+ #ifdef CONFIG_OC_LINCAN_CARD_pcisja1000mm
+ {"pcisja1000mm", pcisja1000mm_register, 0},
+ #endif
#ifdef CONFIG_OC_LINCAN_CARD_pimx1
{"pimx1", pimx1_register, 0},
#endif
--- /dev/null
+/**************************************************************************/
+/* File: pcisja1000mm.c - SJA1000 directly mapped into PCI mem region 0 */
+/* */
+/* LinCAN - (Not only) Linux CAN bus driver */
+/* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz> */
+/* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz> */
+/* Funded by OCERA and FRESCOR IST projects */
+/* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl> */
+/* */
+/* LinCAN is free software; you can redistribute it and/or modify it */
+/* under terms of the GNU General Public License as published by the */
+/* Free Software Foundation; either version 2, or (at your option) any */
+/* later version. LinCAN is distributed in the hope that it will be */
+/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
+/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* General Public License for more details. You should have received a */
+/* copy of the GNU General Public License along with LinCAN; see file */
+/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
+/* Cambridge, MA 02139, USA. */
+/* */
+/* To allow use of LinCAN in the compact embedded systems firmware */
+/* and RT-executives (RTEMS for example), main authors agree with next */
+/* special exception: */
+/* */
+/* Including LinCAN header files in a file, instantiating LinCAN generics */
+/* or templates, or linking other files with LinCAN objects to produce */
+/* an application image/executable, does not by itself cause the */
+/* resulting application image/executable to be covered by */
+/* the GNU General Public License. */
+/* This exception does not however invalidate any other reasons */
+/* why the executable file might be covered by the GNU Public License. */
+/* Publication of enhanced or derived LinCAN files is required although. */
+/**************************************************************************/
+
+#include "../include/can.h"
+#include "../include/can_sysdep.h"
+#include "../include/main.h"
+#include "../include/sja1000p.h"
+
+#ifdef CAN_ENABLE_PCI_SUPPORT
+
+#define DIRECT_PCISJA100_VENDOR 0x1b36
+#define DIRECT_PCISJA100_ID 0xbeef
+
+#define PCISJA1000MM_OCR_DEFAULT_STD 0xDA
+
+#define PCISJA1000MM_BYTES_PER_CIRCUIT 0x80
+
+void pcisja1000mm_disconnect_irq(struct candevice_t *candev)
+{
+}
+
+void pcisja1000mm_connect_irq(struct candevice_t *candev)
+{
+}
+
+int pcisja1000mm_request_io(struct candevice_t *candev)
+{
+ unsigned long io_addr;
+ int i;
+
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+ if(pci_request_region(candev->sysdevptr.pcidev, 0, "pcisja1000mm") != 0){
+ CANMSG("Request of pcisja1000mm range failed\n");
+ return -ENODEV;
+ }
+ #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+ if(pci_request_regions(candev->sysdevptr.pcidev, "pcisja1000mm") != 0){
+ CANMSG("Request of pcisja1000mm regions failed\n");
+ return -ENODEV;
+ }
+ #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+
+ io_addr=pci_resource_start(candev->sysdevptr.pcidev,0);;
+ if (!(candev->dev_base_addr = ioremap(io_addr,
+ pci_resource_len(candev->sysdevptr.pcidev,0)))) {
+ CANMSG("Unable to access I/O memory at: 0x%lx\n", io_addr);
+ goto error_ioremap_io;
+ }
+
+ candev->io_addr=io_addr;
+
+ /*
+ * this is redundant with chip initialization, but remap address
+ * can change when resources are temporarily released
+ */
+ for(i=0;i<candev->nr_all_chips;i++) {
+ struct canchip_t *chip=candev->chip[i];
+ if(!chip) continue;
+ chip->chip_base_addr = candev->dev_base_addr +
+ i * PCISJA1000MM_BYTES_PER_CIRCUIT;
+ if(!chip->msgobj[0]) continue;
+ chip->msgobj[0]->obj_base_addr=chip->chip_base_addr;
+ }
+
+ pcisja1000mm_disconnect_irq(candev);
+
+ return 0;
+
+error_ioremap_io:
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+ pci_release_region(candev->sysdevptr.pcidev, 0);
+ #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+ pci_release_regions(candev->sysdevptr.pcidev);
+ #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+ return -ENODEV;
+}
+
+int pcisja1000mm_release_io(struct candevice_t *candev)
+{
+ pcisja1000mm_disconnect_irq(candev);
+
+ iounmap(candev->dev_base_addr);
+
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
+ pci_release_region(candev->sysdevptr.pcidev, 0);
+ #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+ pci_release_regions(candev->sysdevptr.pcidev);
+ #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
+
+ return 0;
+}
+
+
+void pcisja1000mm_write_register(unsigned data, can_ioptr_t address)
+{
+ can_writeb(data,address);
+}
+
+unsigned pcisja1000mm_read_register(can_ioptr_t address)
+{
+ return can_readb(address);
+}
+
+int pcisja1000mm_reset(struct candevice_t *candev)
+{
+ int i=0,chip_nr;
+ struct canchip_t *chip;
+ unsigned cdr;
+
+ DEBUGMSG("Resetting pcisja1000mm hardware ...\n");
+
+ pcisja1000mm_disconnect_irq(candev);
+
+ for(chip_nr=0;chip_nr<candev->nr_all_chips;chip_nr++){
+ if(!candev->chip[chip_nr]) continue;
+ chip=candev->chip[chip_nr];
+
+ pcisja1000mm_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
+ udelay(1000);
+
+ cdr=pcisja1000mm_read_register(chip->chip_base_addr+SJACDR);
+ pcisja1000mm_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
+
+ pcisja1000mm_write_register(0, chip->chip_base_addr+SJAIER);
+
+ i=20;
+ pcisja1000mm_write_register(0, chip->chip_base_addr+SJAMOD);
+ while (pcisja1000mm_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM){
+ if(!i--) return -ENODEV;
+ udelay(1000);
+ pcisja1000mm_write_register(0, chip->chip_base_addr+SJAMOD);
+ }
+
+ cdr=pcisja1000mm_read_register(chip->chip_base_addr+SJACDR);
+ pcisja1000mm_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
+
+ pcisja1000mm_write_register(0, chip->chip_base_addr+SJAIER);
+
+ pcisja1000mm_read_register(chip->chip_base_addr+SJAIR);
+ }
+
+
+ pcisja1000mm_connect_irq(candev);
+
+ return 0;
+}
+
+int pcisja1000mm_init_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev;
+ int i;
+
+ pcidev = can_pci_get_next_untaken_device(DIRECT_PCISJA100_VENDOR, DIRECT_PCISJA100_ID);
+ if(pcidev == NULL)
+ return -ENODEV;
+
+ if (pci_enable_device (pcidev)){
+ printk(KERN_CRIT "Setup of PCISJA1000MM failed\n");
+ can_pci_dev_put(pcidev);
+ return -EIO;
+ }
+ candev->sysdevptr.pcidev=pcidev;
+
+ for(i=0;i<1;i++){
+
+ if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){
+ printk(KERN_ERR "PCISJA1000MM region %d is not memory\n",i);
+ goto error_ret;
+ }
+ }
+ candev->io_addr=pci_resource_start(pcidev,0); /*IO window for SJA1000 chips*/
+ candev->dev_base_addr=can_ulong2ioptr(candev->io_addr);
+ candev->res_addr=0;
+
+ /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
+
+ candev->nr_82527_chips=0;
+ candev->nr_sja1000_chips=1;
+ candev->nr_all_chips=1;
+
+ return 0;
+
+error_ret:
+
+ printk(KERN_CRIT "Setup of PCISJA1000MM failed\n");
+ pci_disable_device (pcidev);
+ can_pci_dev_put(pcidev);
+ return -EIO;
+}
+
+void pcisja1000mm_done_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+ can_pci_dev_put(pcidev);
+}
+
+int pcisja1000mm_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+
+ if(candev->sysdevptr.pcidev==NULL)
+ return -ENODEV;
+
+ candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
+
+ sja1000p_fill_chipspecops(candev->chip[chipnr]);
+ candev->chip[chipnr]->chip_base_addr=
+ can_ioport2ioptr(candev->io_addr+chipnr*PCISJA1000MM_BYTES_PER_CIRCUIT);
+
+ 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 = sjaCDR_CBP | sjaCDR_CLK_OFF;
+ candev->chip[chipnr]->sja_ocr_reg = PCISJA1000MM_OCR_DEFAULT_STD;
+ candev->chip[chipnr]->clock = 16000000;
+ candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
+
+ return 0;
+}
+
+int pcisja1000mm_init_obj_data(struct canchip_t *chip, int objnr)
+{
+ chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
+ return 0;
+}
+
+int pcisja1000mm_program_irq(struct candevice_t *candev)
+{
+
+ return 0;
+}
+
+int pcisja1000mm_register(struct hwspecops_t *hwspecops)
+{
+ hwspecops->request_io = pcisja1000mm_request_io;
+ hwspecops->release_io = pcisja1000mm_release_io;
+ hwspecops->reset = pcisja1000mm_reset;
+ hwspecops->init_hw_data = pcisja1000mm_init_hw_data;
+ hwspecops->done_hw_data = pcisja1000mm_done_hw_data;
+ hwspecops->init_chip_data = pcisja1000mm_init_chip_data;
+ hwspecops->init_obj_data = pcisja1000mm_init_obj_data;
+ hwspecops->write_register = pcisja1000mm_write_register;
+ hwspecops->read_register = pcisja1000mm_read_register;
+ hwspecops->program_irq = pcisja1000mm_program_irq;
+ return 0;
+}
+
+
+#endif /*CAN_ENABLE_PCI_SUPPORT*/
static struct canproc_t *base=&can_proc_base;
DEFINE_MUTEX(proc_mutex); /* synchronize access to canproc_t array */
-/* The following functions are needed only for kernel version 2.2. Kernel
- * version 2.4 already defines them for us.
- */
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
+
+#include <linux/seq_file.h>
+
+#define CAN_PROC_SHOW_SINGLE_OPS_DECLARE(ops_name, show_function) \
+static int ops_name##_open(struct inode *inode, struct file *file) \
+{ \
+ return single_open(file, show_function, PDE_DATA(inode)); \
+} \
+static const struct file_operations ops_name = { \
+ .owner = THIS_MODULE, \
+ .open = ops_name##_open, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = single_release, \
+};
+
+typedef struct file_operations can_proc_read_entry_ops_t;
+typedef struct seq_file can_proc_seq_file_t;
+
+static inline void *can_seq_data(can_proc_seq_file_t *sqf)
+{
+ return sqf->private;
+}
+
+#define can_seq_printf seq_printf
+
+struct proc_dir_entry *can_create_proc_read_entry(const char *name,
+ mode_t mode, struct proc_dir_entry *parent,
+ const can_proc_read_entry_ops_t *proc_read_entry_ops, void * data)
+{
+ return proc_create_data(name, mode, parent, proc_read_entry_ops, data);
+}
+
+struct proc_dir_entry *can_proc_mkdir_mode(const char *name, umode_t mode,
+ struct proc_dir_entry *parent)
+{
+ return proc_mkdir_mode(name, mode, parent);
+}
+
+static int can_proc_remove(struct proc_dir_entry *del)
+{
+ if(!del) return -ENODEV;
+ proc_remove(del);
+ return 0;
+}
+
+static inline struct proc_dir_entry *can_proc_symlink(const char *name,
+ struct proc_dir_entry *parent, const char *dest)
+{
+ return proc_symlink(name, parent, dest);
+}
+
+#else /* kernel older than 3.10 */
+
+typedef read_proc_t *can_proc_read_entry_ops_t;
+typedef struct {
+ int len;
+ int limit;
+ char *buf;
+ void *private;
+} can_proc_seq_file_t;
+
+#define CAN_PROC_SHOW_SINGLE_OPS_DECLARE(ops_name, show_function) \
+static int ops_name##_show_wrapper(char *buf, char **start, off_t offset, \
+ int count, int *eof, void *data) \
+{ \
+ can_proc_seq_file_t seq_pos = { .len = 0, .buf = buf, .limit = PAGE_SIZE, \
+ .private = data}; \
+ *eof = 1; \
+ show_function(&seq_pos, data); \
+ return seq_pos.len; \
+} \
+const static can_proc_read_entry_ops_t ops_name = ops_name##_show_wrapper;
+
+static inline void *can_seq_data(can_proc_seq_file_t *sqf)
+{
+ return sqf->private;
+}
+
+static inline int can_seq_printf(can_proc_seq_file_t *sqf, const char *f, ...)
+{
+ int ret;
+ va_list args;
+ va_start(args, f);
+ ret = vsnprintf(sqf->buf + sqf->len, sqf->limit - sqf->len, f, args);
+ sqf->len += ret;
+ if (sqf->len > sqf->limit)
+ sqf->len = sqf->limit;
+ va_end(args);
+ return ret;
+}
+
+struct proc_dir_entry *can_create_proc_read_entry(const char *name,
+ mode_t mode, struct proc_dir_entry *parent,
+ const can_proc_read_entry_ops_t *proc_read_entry_ops, void * data)
+{
+ return create_proc_read_entry(name, mode, parent, *proc_read_entry_ops, data);
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0))
+
+struct proc_dir_entry *can_proc_mkdir_mode(const char *name, umode_t mode,
+ struct proc_dir_entry *parent)
+{
+ return create_proc_entry(name, S_IFDIR | mode, parent);
+}
+
+/* This does not fully follow linux 2.4 and 2.6 prototype to simplify 2.2.x compatibility */
+/* The newer kernels use entry name instead of pointer to the entry */
+static int can_proc_remove(struct proc_dir_entry *del)
+{
+ if(!del) return -ENODEV;
+ remove_proc_entry(del->name, del->parent);
+ return 0;
+}
+
+static inline struct proc_dir_entry *can_proc_symlink(const char *name,
+ struct proc_dir_entry *parent, const char *dest)
+{
+ return proc_symlink(name, parent, dest);
+}
+
+#else /* ancient Linux kernel older than 2.3.0 */
static void can_fill_inode(struct inode *inode, int fill)
{
if (fill)
return new_entry;
}
-static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
+struct proc_dir_entry *can_create_proc_read_entry(const char *name,
+ mode_t mode, struct proc_dir_entry *parent,
+ read_proc_t *read_proc, void * data)
+{
+ return create_proc_read_entry(name, mode, parent, read_proc, data);
+}
+
+struct proc_dir_entry *can_proc_mkdir_mode(const char *name, umode_t mode,
+ struct proc_dir_entry *parent)
+{
+ return can_create_proc_entry(name, S_IFDIR | mode, parent);
+}
+
+static int can_proc_remove(struct proc_dir_entry *del)
{
if (del != NULL) {
- proc_unregister(parent, del->low_ino);
+ proc_unregister(del->parent, del->low_ino);
can_checked_free(del);
return 0;
}
return entry;
}
-#else /* Functions forwarded for kernel 2.4 and above */
-
-static inline struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mode,
- struct proc_dir_entry *parent)
-{
- return create_proc_entry(name, mode, parent);
-}
-
+#endif /* Linux 2.2 - 2.3 kernels */
-/* This does not fully follow linux 2.4 and 2.6 prototype to simplify 2.2.x compatibility */
-/* The newer kernels use entry name instead of pointer to the entry */
-static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
-{
- if(!del) return -ENODEV;
- remove_proc_entry(del->name,parent);
- return 0;
-}
-
-static inline struct proc_dir_entry *can_proc_symlink(const char *name,
- struct proc_dir_entry *parent, const char *dest)
-{
- return proc_symlink(name, parent, dest);
-}
-
-#endif /* Functions required for kernel 2.2 */
+#endif /* Linux kernel 3.6 and 3.10+ */
/* can_init_procdir registers the entire CAN directory tree recursively at
* the proc system.
mutex_init(&proc_mutex);
- base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO |
+ base->can_proc_entry = can_proc_mkdir_mode("can", S_IFDIR | S_IRUGO |
S_IXUGO, CAN_PROC_ROOT);
if (base->can_proc_entry == NULL)
return -ENODEV;
if (remove_channels_from_procdir())
return -ENODEV;
/* name: "can" */
- if (can_remove_proc_entry(base->can_proc_entry, CAN_PROC_ROOT))
+ if (can_proc_remove(base->can_proc_entry))
return -ENODEV;
return 0;
return 0;
}
-static int can_chip_procinfo(char *buf, char **start, off_t offset,
- int count, int *eof, void *data)
+static int can_chip_procinfo_show(can_proc_seq_file_t *sqf, void *data)
{
- struct canchip_t *chip=data;
- int len=0;
+ struct canchip_t *chip=can_seq_data(sqf);
/* Generic chip info */
- len += sprintf(buf+len,"type : %s\n",chip->chip_type);
- len += sprintf(buf+len,"index : %d\n",chip->chip_idx);
- len += sprintf(buf+len,"irq : %d\n",chip->chip_irq);
- len += sprintf(buf+len,"addr : %lu\n",
+ can_seq_printf(sqf, "type : %s\n",chip->chip_type);
+ can_seq_printf(sqf, "index : %d\n",chip->chip_idx);
+ can_seq_printf(sqf, "irq : %d\n",chip->chip_irq);
+ can_seq_printf(sqf, "addr : %lu\n",
can_ioptr2ulong(chip->chip_base_addr));
- len += sprintf(buf+len,"config : %s\n",
+ can_seq_printf(sqf, "config : %s\n",
(chip->flags & CHIP_CONFIGURED) ? "yes":"no");
- len += sprintf(buf+len,"clock : %ld Hz\n",chip->clock);
- len += sprintf(buf+len,"baud : %ld\n",chip->baudrate);
- len += sprintf(buf+len,"num obj : %d\n",chip->max_objects);
-
+ can_seq_printf(sqf, "clock : %ld Hz\n",chip->clock);
+ can_seq_printf(sqf, "baud : %ld\n",chip->baudrate);
+ can_seq_printf(sqf, "num obj : %d\n",chip->max_objects);
#if 0
/* Chip specific info if available */
len += (chip->chipspecops->get_info)(chip,buf+len);
#endif
- *eof = 1;
- return len;
+ return 0;
}
+CAN_PROC_SHOW_SINGLE_OPS_DECLARE(can_chip_procinfo_ops, can_chip_procinfo_show);
int add_channel_to_procdir(struct candevice_t *candev)
{
sprintf(base->channel[i]->ch_name, "channel%d",i);
- base->channel[i]->ch_entry = can_create_proc_entry(
+ base->channel[i]->ch_entry = can_proc_mkdir_mode(
base->channel[i]->ch_name,
S_IFDIR | S_IRUGO |S_IXUGO,
base->can_proc_entry);
add_object_to_procdir(i);
- create_proc_read_entry("chip_info", /* proc entry name */
+ can_create_proc_read_entry("chip_info", /* proc entry name */
0, /* protection mask, 0->default */
base->channel[i]->ch_entry, /* parent dir, NULL->/proc */
- can_chip_procinfo,
+ &can_chip_procinfo_ops,
chips_p[i]);
cc++;
}
}
/* name: base->channel[cc]->ch_name */
- if (can_remove_proc_entry(base->channel[i]->ch_entry,
- base->can_proc_entry)){
+ if (can_proc_remove(base->channel[i]->ch_entry)){
mutex_unlock(&proc_mutex);
return -ENODEV;
}
}
/* name: base->channel[cc]->ch_name */
- if (can_remove_proc_entry(base->channel[i]->ch_entry,
- base->can_proc_entry)){
+ if (can_proc_remove(base->channel[i]->ch_entry)){
mutex_unlock(&proc_mutex);
return -ENODEV;
}
sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
- base->channel[chip_nr]->object[i]->obj_entry = can_create_proc_entry(
+ base->channel[chip_nr]->object[i]->obj_entry = can_proc_mkdir_mode(
base->channel[chip_nr]->object[i]->obj_name,
S_IFDIR | S_IRUGO | S_IXUGO,
base->channel[chip_nr]->ch_entry);
if(!base->channel[chip_nr]->object[i]) continue;
/* name: base->channel[chip_nr]->object[i]->lnk_name */
- if (can_remove_proc_entry( base->channel[chip_nr]->object[i]->lnk,
- base->channel[chip_nr]->object[i]->obj_entry))
+ if (can_proc_remove( base->channel[chip_nr]->object[i]->lnk))
return -ENODEV;
/* name: base->channel[chip_nr]->object[i]->obj_name */
- if (can_remove_proc_entry(
- base->channel[chip_nr]->object[i]->obj_entry,
- base->channel[chip_nr]->ch_entry))
+ if (can_proc_remove(base->channel[chip_nr]->object[i]->obj_entry))
return -ENODEV;
can_checked_free(base->channel[chip_nr]->object[i]);