-/* can_sysdep.h - hides differences between individual Linux kernel
- * versions and RT extensions
+/* can_sysdep.h - hides differences between individual Linux kernel
+ * versions and RT extensions
* Linux CAN-bus device driver.
* Written by Pavel Pisa - OCERA team member
* email:pisa@cmp.felk.cvut.cz
/*
* terrible hack to test rtl_file private_data concept, ugh !!!
- * this would result in crash on architectures, where
+ * this would result in crash on architectures, where
* sizeof(int) < sizeof(void *)
*/
#define can_set_rtl_file_private_data(fptr, p) do{ fptr->f_minor=(long)(p); } while(0)
* @flags: board flags: %PROGRAMMABLE_IRQ .. interrupt number
* can be programmed into board
* @nr_all_chips: number of chips present on the board
- * @nr_82527_chips: number of Intel 8257 chips
+ * @nr_82527_chips: number of Intel 8257 chips
* @nr_sja1000_chips: number of Philips SJA100 chips
* @chip: array of pointers to the chip structures
* @hwspecops: pointer to board specific operations
struct hwspecops_t *hwspecops;
struct canhardware_t *hosthardware_p;
-
+
union {
void *anydev;
#ifdef CAN_ENABLE_PCI_SUPPORT
* @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_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
- * (chip->hostdevice->hwspecops->write_register and
+ * (chip->hostdevice->hwspecops->write_register and
* chip->hostdevice->hwspecops->read_register)
* to speedup can_write_reg() and can_read_reg() functions.
*/
void (*write_register)(unsigned data, can_ioptr_t address);
unsigned (*read_register)(can_ioptr_t address);
-
+
void *chip_data;
-
+
unsigned short sja_cdr_reg; /* sja1000 only! */
unsigned short sja_ocr_reg; /* sja1000 only! */
unsigned short int_cpu_reg; /* intel 82527 only! */
struct chipspecops_t *chipspecops;
struct candevice_t *hostdevice;
-
+
int max_objects; /* 1 for sja1000, 15 for i82527 */
can_spinlock_t chip_lock;
/**
* struct msgobj_t - structure holding communication object state
- * @obj_base_addr:
+ * @obj_base_addr:
* @minor: associated device minor number
* @object: object number in canchip_t structure +1
* @flags: message object flags
* @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
+ * %MSGOBJ_TX_LOCK .. some IRQ routine or callback on some CPU
* is running inside TX activation processing code
* @rx_preconfig_id: place to store RX message identifier for some chip types
* that reuse same object for TX
can_ioptr_t obj_base_addr;
unsigned int minor; /* associated device minor number */
unsigned int object; /* object number in canchip_t +1 for debug printk */
- unsigned long obj_flags;
+ unsigned long obj_flags;
int ret;
struct canque_ends_t *qends;
struct canque_slot_t *tx_slot;
int tx_retry_cnt;
struct timer_list tx_timeout;
-
+
struct canmsg_t rx_msg;
struct canchip_t *hostchip;
-
+
unsigned long rx_preconfig_id;
atomic_t obj_used;
* @request_io: reserve io or memory range for can board
* @release_io: free reserved io memory range
* @reset: hardware reset routine
- * @init_hw_data: called to initialize &candevice_t structure, mainly
+ * @init_hw_data: called to initialize &candevice_t structure, mainly
* @res_add, @nr_all_chips, @nr_82527_chips, @nr_sja1000_chips
* and @flags fields
* @init_chip_data: called initialize each &canchip_t structure, mainly
* @init_obj_data: called initialize each &msgobj_t structure,
* mainly @obj_base_addr field.
* @program_irq: program interrupt generation hardware of the board
- * if flag %PROGRAMMABLE_IRQ is present for specified device/board
+ * if flag %PROGRAMMABLE_IRQ is present for specified device/board
* @write_register: low level write register routine
* @read_register: low level read register routine
*/
int (*chip_config)(struct canchip_t *chip);
int (*baud_rate)(struct canchip_t *chip, int rate, int clock, int sjw,
int sampl_pt, int flags);
- int (*standard_mask)(struct canchip_t *chip, unsigned short code,
+ int (*standard_mask)(struct canchip_t *chip, unsigned short code,
unsigned short mask);
- int (*extended_mask)(struct canchip_t *chip, unsigned long code,
+ int (*extended_mask)(struct canchip_t *chip, unsigned long code,
unsigned long mask);
- int (*message15_mask)(struct canchip_t *chip, unsigned long code,
+ int (*message15_mask)(struct canchip_t *chip, unsigned long code,
unsigned long mask);
int (*clear_objects)(struct canchip_t *chip);
int (*config_irqs)(struct canchip_t *chip, short irqs);
int (*filtch_rq)(struct canchip_t *chip, struct msgobj_t *obj);
int (*enable_configuration)(struct canchip_t *chip);
int (*disable_configuration)(struct canchip_t *chip);
- int (*set_btregs)(struct canchip_t *chip, unsigned short btr0,
+ int (*set_btregs)(struct canchip_t *chip, unsigned short btr0,
unsigned short btr1);
int (*attach_to_chip)(struct canchip_t *chip);
int (*release_chip)(struct canchip_t *chip);
#define CONFIG_OC_LINCAN_DYNAMICIO
#endif
-/* Inline function to write to the hardware registers. The argument reg_offs is
+/* Inline function to write to the hardware registers. The argument reg_offs is
* relative to the memory map of the chip and not the absolute memory reg_offs.
*/
extern inline void can_write_reg(const struct canchip_t *chip, unsigned char data, unsigned reg_offs)
char lnk_name[20];
char lnk_dev[20];
struct proc_dir_entry *lnk;
-};
+};
* email:pisa@cmp.felk.cvut.cz
* This software is released under the GPL-License.
* Version lincan-0.3 17 Jun 2004
- */
+ */
/* This file is intended as a bfadcan file for currently unsupported hardware.
* Once you've changed/added the functions specific to your hardware it is
*
* The function bfadcan_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.
+ * will have to add the code to reserve this memory as well.
* %IO_RANGE is the io-memory range that gets reserved, please adjust according
* your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
* #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
* bfadcan_reset - hardware reset routine
* @candev: Pointer to candevice/board structure
*
- * The function bfadcan_reset() is used to give a hardware reset. This is
- * rather hardware specific so I haven't included example code. Don't forget to
+ * The function bfadcan_reset() is used to give a hardware reset. This is
+ * rather hardware specific so I haven't included example code. Don't forget to
* check the reset status of the chip before returning.
* Return Value: The function returns zero on success or %-ENODEV on failure
* File: src/bfadcan.c
int i;
struct canchip_t *chip=candev->chip[0];
unsigned cdr;
-
+
bfadcan_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
udelay(1000);
-
+
cdr=bfadcan_read_register(chip->chip_base_addr+SJACDR);
bfadcan_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
bfadcan_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
bfadcan_write_register(0, chip->chip_base_addr+SJAIER);
-
+
return 0;
}
* Return Value: The function always returns zero
* File: src/bfadcan.c
*/
-int bfadcan_init_hw_data(struct candevice_t *candev)
+int bfadcan_init_hw_data(struct candevice_t *candev)
{
candev->res_addr=RESET_ADDR;
candev->nr_82527_chips=NR_82527;
* The entry @int_clk_reg holds hardware specific options for the Clock Out
* register. Options defined in the %i82527.h file:
* %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
- * The entry @int_bus_reg holds hardware specific options for the Bus
+ * The entry @int_bus_reg holds hardware specific options for the Bus
* Configuration register. Options defined in the %i82527.h file:
* %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
* The entry @int_cpu_reg holds hardware specific options for the cpu interface
* CAN chip. In case of the sja1000 there's only one message object but on the
* i82527 chip there are 15.
* The code below is for a i82527 chip and initializes the object base addresses
- * The entry @obj_base_addr represents the first memory address of the message
+ * The entry @obj_base_addr represents the first memory address of the message
* object. In case of the sja1000 @obj_base_addr is taken the same as the chips
* base address.
* Unless the hardware uses a segmented memory map, flags can be set zero.
int bfadcan_init_obj_data(struct canchip_t *chip, int objnr)
{
chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
-
+
return 0;
}
* bfadcan_program_irq - program interrupts
* @candev: Pointer to candevice/board structure
*
- * The function bfadcan_program_irq() is used for hardware that uses
+ * The function bfadcan_program_irq() is used for hardware that uses
* programmable interrupts. If your hardware doesn't use programmable interrupts
- * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and
- * leave this function unedited. Again this function is hardware specific so
+ * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and
+ * leave this function unedited. Again this function is hardware specific so
* there's no example code.
* Return value: The function returns zero on success or %-ENODEV on failure
* File: src/bfadcan.c
/**
* canqueue_notify_chip - notification callback handler for CAN chips ends of queues
* @qends: pointer to the callback side ends structure
- * @qedge: edge which invoked notification
+ * @qedge: edge which invoked notification
* @what: notification type
*
* This function has to deal with more possible cases. It can be called from
can_msgobj_set_fl(obj,FILTCH_REQUEST);
canqueue_wake_chip_worker(qends, chip, obj);
#endif /*CAN_WITH_RTL*/
-
+
break;
}
}
int ret;
ret=canqueue_ends_init_gen(qends);
if(ret<0) return ret;
-
+
qends->context=NULL;
#ifndef CAN_WITH_RTL
init_waitqueue_head(&qends->endinfo.chipinfo.daemonq);
int canqueue_ends_done_chip(struct canque_ends_t *qends)
{
int delayed;
-
+
/* Finish or kill all outgoing edges listed in inends */
delayed=canqueue_ends_kill_inlist(qends, 1);
/* Kill all incoming edges listed in outends */
CANMSG("msgobj_done: not registered in the canchip_t\n");
obj->hostchip=NULL;
}
-
+
if((obj->minor>=0)) {
if(objects_p[obj->minor] == obj)
objects_p[obj->minor] = NULL;
else
CANMSG("msgobj_done: not registered as minor\n");
}
-
+
del_timer_sync(&obj->tx_timeout);
if(obj->qends) {
}
can_chip_free_irq(chip);
-
+
can_synchronize_irq(chip->chip_irq);
-
+
for(i=0; i<chip->max_objects; i++){
if((obj=chip->msgobj[i])==NULL)
continue;
msgobj_done(obj);
can_checked_free(obj);
}
-
+
can_checked_free(chip->chipspecops);
chip->chipspecops=NULL;
{
int i;
struct canchip_t *chip;
-
+
for(i=0; i<candev->nr_all_chips; i++){
if((chip=candev->chip[i])==NULL)
continue;
canchip_done(chip);
can_checked_free(chip);
-
+
}
if(candev->flags & CANDEV_IO_RESERVED) {
candev->hwspecops->release_io(candev);
{
int i;
struct candevice_t *candev;
-
+
for(i=0; i<canhw->nr_boards; i++){
if((candev=canhw->candevice[i])==NULL)
continue;
sema_init(&kthread->startstop_sem,0);
/* We need to do a memory barrier here to be sure that
- the flags are visible on all CPUs.
+ the flags are visible on all CPUs.
*/
mb();
kthread->terminate = 1;
/* We need to do a memory barrier here to be sure that
- the flags are visible on all CPUs.
+ the flags are visible on all CPUs.
*/
mb();
kill_proc(kthread->thread->pid, SIGKILL, 1);
#endif
#endif
-#if !defined (__GENKSYMS__)
+#if !defined (__GENKSYMS__)
#if (defined (MODVERSIONS) && !defined(NOVER))
#include <linux/modversions.h>
/*#include "../include/main.ver"*/
struct file_operations can_fops=
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0))
- owner: THIS_MODULE,
+ owner: THIS_MODULE,
#endif
read: can_read,
write: can_write,
/*
2.6 kernel attributes for sysfs
-
+
static ssize_t show_xxx(struct class_device *cdev, char *buf)
{
return sprintf(buf, "xxxx\n");
for (i=0; i<hardware_p->nr_boards; i++) {
candev=hardware_p->candevice[i];
- if (candev->hwspecops->request_io(candev))
+ if (candev->hwspecops->request_io(candev))
goto request_io_error;
candev->flags|=CANDEV_IO_RESERVED;
}
for (i=0; i<hardware_p->nr_boards; i++) {
candev=hardware_p->candevice[i];
- if (candev->hwspecops->reset(candev))
+ if (candev->hwspecops->reset(candev))
goto reset_error;
}
}
chip->flags |= CHIP_ATTACHED;
-
+
if(can_chip_setup_irq(chip)<0) {
CANMSG("Error to setup chip IRQ\n");
goto interrupt_error;
#ifdef CONFIG_PROC_FS
proc_error: ;
CANMSG("Error registering /proc entry.\n");
- goto memory_error;
+ goto memory_error;
#endif
interrupt_error: ;
CANMSG("No CAN devices or driver setup error.\n");
register_error:
- if ( can_del_mem_list() )
+ if ( can_del_mem_list() )
CANMSG("Error deallocating memory\n");
return -ENODEV;
#ifdef CONFIG_PROC_FS
if (can_delete_procdir())
- CANMSG("Error unregistering /proc/can entry.\n");
+ CANMSG("Error unregistering /proc/can entry.\n");
#endif
#if defined(CONFIG_DEVFS_FS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
canqueue_rtl_done();
#endif /*CAN_WITH_RTL*/
- if ( can_del_mem_list() )
+ if ( can_del_mem_list() )
CANMSG("Error deallocating memory\n");
unregister_chrdev(major,DEVICE_NAME);
/* Check wether the supplied number of io addresses is correct. */
io_needed=i;
- while ( (io[io_supplied] != -1) & (io_supplied<MAX_HW_CARDS) )
+ while ( (io[io_supplied] != -1) & (io_supplied<MAX_HW_CARDS) )
io_supplied++;
if (io_needed != io_supplied) {
CANMSG("Invalid number of io addresses.\n");
if (minor[0] != -1) {
minor_needed=irq_needed;
while ((minor[minor_supplied] != -1) & (minor_supplied<MAX_IRQ))
- minor_supplied++;
+ minor_supplied++;
if (minor_supplied != minor_needed) {
CANMSG("Invalid number of minor numbers.\n");
CANMSG("Supplied hardware needs %d minor number(s).\n",minor_needed);
* email:pisa@cmp.felk.cvut.cz
* This software is released under the GPL-License.
* Version lincan-0.3 17 Jun 2004
- */
+ */
#include "../include/can.h"
#include "../include/can_sysdep.h"
struct proc_dir_entry *new_entry = NULL;
char *namestore;
int namelen;
-
+
if(!name || !parent)
return NULL;
namelen=strlen(name);
if(!namelen)
return NULL;
- new_entry = (struct proc_dir_entry *)
+ new_entry = (struct proc_dir_entry *)
can_checked_malloc(sizeof(struct proc_dir_entry)+namelen+1);
if (new_entry == NULL)
static int can_proc_readlink(struct proc_dir_entry *ent, char *page)
{
char *link_dest = (char*)ent->data;
-
+
strcpy(page, link_dest);
return strlen(link_dest);
}
struct proc_dir_entry *parent, const char *dest)
{
struct proc_dir_entry *entry;
-
-
+
+
entry = can_create_proc_entry(name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, parent);
if (entry == NULL)
return NULL;
{
int board;
struct candevice_t *candev;
- base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO |
+ base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO |
S_IXUGO, CAN_PROC_ROOT);
if (base->can_proc_entry == NULL)
return -ENODEV;
for (board=0; board<hardware_p->nr_boards; board++) {
candev=hardware_p->candevice[board];
if(candev) add_channel_to_procdir(candev);
- }
+ }
return 0;
}
return 0;
}
-static int can_chip_procinfo(char *buf, char **start, off_t offset,
+static int can_chip_procinfo(char *buf, char **start, off_t offset,
int count, int *eof, void *data)
{
struct canchip_t *chip=data;
return -ENOMEM;
sprintf(base->channel[cc]->ch_name, "channel%d",cc);
-
+
base->channel[cc]->ch_entry = can_create_proc_entry(
base->channel[cc]->ch_name,
S_IFDIR | S_IRUGO |S_IXUGO,
candev->chip[i]);
cc++;
- }
+ }
return 0;
}
int remove_channel_from_procdir(void)
{
-
+
while (cc != 0) {
cc--;
-
+
if(!base->channel[cc]) continue;
remove_proc_entry("chip_info", base->channel[cc]->ch_entry);
-
+
if (remove_object_from_procdir(cc))
- return -ENODEV;
-
+ return -ENODEV;
+
/* name: base->channel[cc]->ch_name */
if (can_remove_proc_entry(base->channel[cc]->ch_entry,
base->can_proc_entry))
return -ENODEV;
-
+
can_checked_free(base->channel[cc]);
base->channel[cc] = NULL;
}
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_name,
S_IFDIR | S_IRUGO | S_IXUGO,
}
return 0;
-}
+}
int remove_object_from_procdir(int chip_nr)
{
for (i=0; i<obj; i++) {
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))
+ base->channel[chip_nr]->object[i]->obj_entry))
return -ENODEV;
/* name: base->channel[chip_nr]->object[i]->obj_name */
if (can_remove_proc_entry(
* email:pisa@cmp.felk.cvut.cz
* This software is released under the GPL-License.
* Version lincan-0.3 17 Jun 2004
- */
+ */
#include "../include/can.h"
#include "../include/can_sysdep.h"
{
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++){
/**
* can_check_dev_taken - checks if bus device description is already taken by driver
- * @anydev: pointer to bus specific Linux device description
+ * @anydev: pointer to bus specific Linux device description
*
* Returns: Returns 1 if device is already used by LinCAN driver, 0 otherwise.
*/
if(boarddev == anydev)
return 1;
}
-
+
return 0;
}
{
static int next_minor=0;
int i;
-
+
if(minorbase>=0)
next_minor=minorbase;
if(next_minor>=MAX_TOT_MSGOBJS)
{
static int next_chip_slot=0;
int i;
-
+
if(next_chip_slot>=MAX_TOT_CHIPS)
next_chip_slot=0;
i=next_chip_slot;
* @irq_param_idx_p: pointer to the index into arrays of the per CAN channel IRQ parameters
*
* The function builds representation of the one board from parameters provided
- * in the module parameters arrays:
+ * in the module parameters arrays:
* @hw[card] .. hardware type,
* @io[card] .. base IO address,
* @baudrate[chan_param_idx] .. per channel baudrate,
* The indexes are advanced after consumed parameters if the registration is successful.
*
* The hardware specific operations of the device/board are initialized by call to
- * init_hwspecops() function. Then board data are initialized by board specific
+ * init_hwspecops() function. Then board data are initialized by board specific
* init_hw_data() function. Then chips and objects representation is build by
* init_chip_struct() function. If all above steps are successful, chips and
- * message objects are registered into global arrays.
+ * message objects are registered into global arrays.
*
* Return Value: returns negative number in the case of fail
*/
long bd;
int irqsig=-1;
long clock;
-
+
candev=(struct candevice_t *)can_checked_malloc(sizeof(struct candevice_t));
if (candev==NULL)
return -ENOMEM;
if(chipnr<irqnum)
irqsig=irq[*irq_param_idx_p+chipnr];
-
+
bd=baudrate[*chan_param_idx_p+chipnr];
if(!bd) bd=baudrate[0];
-
+
if ((ret=init_chip_struct(candev, chipnr, irqsig, bd*1000, clock*1000)))
goto error_chip;
}
-
+
for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
int objnr;
register_chip_struct(chip, m);
-
+
for (objnr=0; objnr<chip->max_objects; objnr++) {
register_obj_struct(chip->msgobj[objnr], m);
if(m>=0) m++;
hardware_p->candevice[card]=NULL;
can_checked_free(candev);
return ret;
-
+
}
/**
* @baudrate: baudrate in the units of 1Bd
* @clock: optional chip base clock frequency in 1Hz step
*
- * Chip structure is allocated and chip specific operations are filled by
+ * Chip structure is allocated and chip specific operations are filled by
* call to board specific init_chip_data() which calls chip specific
- * fill_chipspecops(). The message objects are generated by
+ * fill_chipspecops(). The message objects are generated by
* calls to init_obj_struct() function.
*
* Return Value: returns negative number in the case of fail
obj=(struct msgobj_t *)can_checked_malloc(sizeof(struct msgobj_t));
hostchip->msgobj[objnr]=obj;
- if (obj == NULL)
+ if (obj == NULL)
return -ENOMEM;
memset(obj, 0, sizeof(struct msgobj_t));
ret=candev->hwspecops->init_obj_data(hostchip,objnr);
if(ret<0) return ret;
-
+
return 0;
}
int init_hwspecops(struct candevice_t *candev, int *irqnum_p)
{
const struct boardtype_t *brp;
-
+
brp = boardtype_find(candev->hwname);
-
+
if(!brp) {
CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",candev->hwname);
return -EINVAL;
}
-
+
if(irqnum_p)
*irqnum_p=brp->irqnum;
brp->board_register(candev->hwspecops);