📄 sja1000.c
字号:
/*
* sja1000.c
* Copyright (c) 2001 J黵gen Eder <Juergen.Eder@gmx.de>
*
* A general chipset driver for CAN cards with SJA1000 (82C200 should work
* in CAN 2.0A mode). To use this, the hardware driver is needed (e.g. can200par.o
* or elektor_canpar.o)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define EXPORT_SYMTAB
#include <linux/version.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/parport.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/time.h>
#include "trace.h"
#include "sja1000.h"
#include "canbus4linux.h"
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
int sja1000_set_baudrate(struct sja1000_admin *pSja1000Par, unsigned long baudrate);
int sja1000_set_baudrate_by_constant(struct sja1000_admin *pSja1000Par, unsigned long baudrate);
int sja1000_set_acceptance_filter(struct sja1000_admin *pSja1000Par, struct canbus_acceptance_filter *filter);
int sja1000_check_chipset(struct sja1000_admin *pSja1000Par);
int sja1000_activate_device(struct sja1000_admin *pSja1000Par);
int sja1000_init_device(struct sja1000_admin *pSja1000Par);
int sja1000_deactivate_device(struct sja1000_admin *pSja1000Par);
int sja1000_set_register(struct sja1000_admin *pSja1000Par, int addresse, unsigned int value);
int sja1000_get_register(struct sja1000_admin *pSja1000Par, int addresse, int *value);
#define NUM_SJA1000_DEVICES 10
static struct sja1000_admin sja1000_admin[NUM_SJA1000_DEVICES];
#define SJA1000_DECLCHIP(x) \
struct sja1000_access * chip = &((x)->access); \
void * chip_data = (x)->pDeviceParm; \
do {} while (0) // makes the user put ';' after it
#define SJA1000_TEST_DECLCHIP(x) \
struct sja1000_access * chip; \
void * chip_data; \
if (!(x)) \
return -ENODEV; \
chip = &((x)->access); \
chip_data = (x)->pDeviceParm; \
do {} while (0) // makes the user put ';' after it
/***************************************************************************************/
static void sja1000_LockRegister(struct sja1000_admin *pSja1000Par)
{
spin_lock_irqsave(&pSja1000Par->irq_lock,pSja1000Par->lock_flags);
}
/***************************************************************************************/
static void sja1000_UnLockRegister(struct sja1000_admin *pSja1000Par)
{
spin_unlock_irqrestore(&pSja1000Par->irq_lock,pSja1000Par->lock_flags);
}
/***************************************************************************************/
static void sja1000_WriteRegister(struct sja1000_admin *pSja1000Par, u8 addr, u8 value)
{
SJA1000_DECLCHIP(pSja1000Par);
sja1000_LockRegister(pSja1000Par);
chip->pWriteToRegister(chip_data, addr, value);
sja1000_UnLockRegister(pSja1000Par);
}
/***************************************************************************************/
static u8 sja1000_ReadRegister(struct sja1000_admin *pSja1000Par, u8 addr)
{
u8 ret=0;
SJA1000_DECLCHIP(pSja1000Par);
sja1000_LockRegister(pSja1000Par);
ret = chip->pReadFromRegister(chip_data, addr);
sja1000_UnLockRegister(pSja1000Par);
return ret;
}
/***************************************************************************************/
static void sja1000_WriteRegisterRR(struct sja1000_admin *pSja1000Par, u8 addr, u8 value)
{
SJA1000_DECLCHIP(pSja1000Par);
sja1000_LockRegister(pSja1000Par);
chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) | 0x01);
chip->pWriteToRegister(chip_data, addr, value);
chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) & 0x3e);
sja1000_UnLockRegister(pSja1000Par);
}
/***************************************************************************************/
static u8 sja1000_ReadRegisterRR(struct sja1000_admin *pSja1000Par, u8 addr)
{
u8 ret=0;
SJA1000_DECLCHIP(pSja1000Par);
sja1000_LockRegister(pSja1000Par);
chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) | 0x01);
ret = chip->pReadFromRegister(chip_data, addr);
chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) & 0x3e);
sja1000_UnLockRegister(pSja1000Par);
return ret;
}
/***************************************************************************************/
int sja1000_open_device(struct sja1000_admin *pSja1000Par)
{
int ret;
SJA1000_TEST_DECLCHIP(pSja1000Par);
ret = chip->pOpenCanDevice(chip_data);
sja1000_activate_device(pSja1000Par);
return ret;
}
/***************************************************************************************/
int sja1000_close_device(struct sja1000_admin *pSja1000Par)
{
int ret;
SJA1000_TEST_DECLCHIP(pSja1000Par);
ret = chip->pCloseCanDevice(chip_data);
sja1000_deactivate_device(pSja1000Par);
return ret;
}
/***************************************************************************************/
int sja1000_init_device(struct sja1000_admin *pSja1000Par)
{
SJA1000_TEST_DECLCHIP(pSja1000Par);
if (pSja1000Par->bCan_2B)
{
TRACE("Init Pelican");
sja1000_WriteRegisterRR(pSja1000Par, 0, 0x08); // Acceptance Filter Mode: single
sja1000_WriteRegisterRR(pSja1000Par, 31, 0x80 | sja1000_ReadRegisterRR(pSja1000Par, 31)); // Pelican einschalten
sja1000_WriteRegisterRR(pSja1000Par, 4, 0xff); // IRQ's
sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control
sja1000_WriteRegisterRR(pSja1000Par, 12, 0); // error code capture
sja1000_WriteRegisterRR(pSja1000Par, 13, 96); // error warning limit
sja1000_WriteRegisterRR(pSja1000Par, 14, 0x00); // RX error counter
sja1000_WriteRegisterRR(pSja1000Par, 15, 0x00); // TX error counter
sja1000_ReadRegister(pSja1000Par, 3);
}
else
{
TRACE("Init BasicCan");
sja1000_WriteRegisterRR(pSja1000Par, 31, 0x7f & sja1000_ReadRegisterRR(pSja1000Par, 31)); // Pelican ausschalten
sja1000_WriteRegisterRR(pSja1000Par, 0, 0x3f); // Reset Request=1 + alle IRQs freigeben
sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control
sja1000_WriteRegister(pSja1000Par, 10, 0x25); // Bit ID3 bis ID10
sja1000_WriteRegister(pSja1000Par, 11, 0x88); // Bit ID0 bis ID2, RTR-Flag, Data-Length-Code
}
return 0;
}
/***************************************************************************************/
int sja1000_activate_device(struct sja1000_admin *pSja1000Par)
{
SJA1000_TEST_DECLCHIP(pSja1000Par);
if (pSja1000Par->bCan_2B)
{
TRACE("Activate Pelican");
sja1000_WriteRegisterRR(pSja1000Par, 4, 0xff); // IRQ's
sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control
sja1000_WriteRegister(pSja1000Par, 0, 0x00); // Reset Request =0
sja1000_ReadRegister(pSja1000Par, 3);
}
else
{
TRACE("Activate BasicCan");
sja1000_WriteRegisterRR(pSja1000Par, 0, 0x3f); // Reset Request=1 + alle IRQs freigeben
sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control
sja1000_WriteRegister(pSja1000Par, 0, 0x3e); // Reset Request =0
}
return 0;
}
/***************************************************************************************/
int sja1000_deactivate_device(struct sja1000_admin *pSja1000Par)
{
SJA1000_TEST_DECLCHIP(pSja1000Par);
if (pSja1000Par->bCan_2B)
{
TRACE("Activate Pelican");
sja1000_WriteRegisterRR(pSja1000Par, 4,0); // IRQ's
}
else
{
TRACE("Activate BasicCan");
sja1000_WriteRegisterRR(pSja1000Par, 0,0); // Reset Request=1 + alle IRQs freigeben
}
return 0;
}
/***************************************************************************************/
static int iSetSJA1000Baudrate(struct sja1000_admin *pSja1000Par)
{
u8 tmp;
unsigned long wbaud;
long bpr,ts1,ts2;
int ts2array[]={2,3,4,5,1,6,7,0};
int x;
long testwert,neutest=50;
INFO_TRACE("Calculating baudrate for frequency %d",pSja1000Par->access.chipset_frequency);
wbaud = pSja1000Par->iBaudrate;
if (wbaud < 5000) wbaud = 5000;
if (wbaud > 2000000) wbaud = 2000000;
pSja1000Par->iBaudrate = wbaud;
testwert = pSja1000Par->access.chipset_frequency/(wbaud*2);
while(neutest > 0)
{
for(x=0;x<sizeof(ts2array)/sizeof(int);x++)
{
ts2 = ts2array[x];
for(ts1=0x0f;ts1>=0;ts1--)
{
if ((testwert % (ts1+ts2+3)) == 0)
{
bpr = testwert/(ts1+ts2+3)-1;
if ((bpr >= 0) && (bpr < 0x40))
{
bpr |= 0x40; // SJW.0 setzen
tmp = (u8)((ts2 << 4) + ts1);
TRACE("%ld ts2 %ld ts1 %ld BPR0 0x%lx BPR1 0x%x",testwert,ts2, ts1, bpr,tmp);
sja1000_WriteRegisterRR(pSja1000Par, 6, (u8)bpr);
sja1000_WriteRegisterRR(pSja1000Par, 7, tmp);
return 1;
}
}
}
}
testwert++;
neutest--;
}
TRACE("Can't set baudrate");
return 0;
}
/***************************************************************************************/
int sja1000_set_baudrate(struct sja1000_admin *pSja1000Par, unsigned long baudrate)
{
if(!pSja1000Par)
return -ENODEV;
pSja1000Par->iBaudrate = baudrate;
if(!iSetSJA1000Baudrate(pSja1000Par))
{
return -EINVAL;
}
return 0;
}
/***************************************************************************************/
const unsigned long baudrate_list[]=
{
20000,
50000,
100000,
125000,
150000,
200000,
500000,
1000000,
0
};
int sja1000_get_properties(struct sja1000_admin *pSja1000Par, struct canbus_properties *props)
{
static const int basiccan[]=
{
CANBUS_CMD_ENTER_STANDBY,CANBUS_CMD_ABORT_TRANSMISSION,
CANBUS_CMD_CLEAR_OVERRUN,CANBUS_CMD_LEAVE_STANDBY,0
};
static const int pelican[]=
{
CANBUS_CMD_ENTER_STANDBY,CANBUS_CMD_ABORT_TRANSMISSION,
CANBUS_CMD_CLEAR_OVERRUN,CANBUS_CMD_LEAVE_STANDBY,
CANBUS_CMD_SELF_RECEPTION_REQUEST,CANBUS_CMD_LISTEN_ON,
CANBUS_CMD_LISTEN_OFF,0
};
int t;
props->min = 20000;
props->max = 1000000;
props->chipset_flags = pSja1000Par->access.bCanChipsetFlags;
props->number_baudrates = 0;
props->number_registers = 128*2;
/* This function is called by an application to get all provided commands.
*/
if(!pSja1000Par)
return -ENODEV;
if(pSja1000Par->bCan_2B)
{
for(t=0;pelican[t];t++)
props->commands[t] = pelican[t];
props->number_commands = t;
}
else
{
for(t=0;basiccan[t];t++)
props->commands[t] = basiccan[t];
props->number_commands = t;
}
for(t=0;baudrate_list[t] && (t<CANBUS_NUMBER_OF_CONSTANT_BAUDRATES);t++)
props->baudrates[t] = baudrate_list[t];
//props->number_baudrates = t;
return 0;
}
/***************************************************************************************/
int sja1000_set_register(struct sja1000_admin *pSja1000Par, int addresse, unsigned int value)
{
int ret = -ENOSYS;
/* The SJA1000 has 128 normal register and 128 'reset mode' register (in PELICAN mode)
* To get a hardware abstraction in above layers, this function accepts following
* addresses:
* 0...7f = normal mode registers
* 80..ff = reset mode register 0...7f
*/
if(pSja1000Par)
{
if((addresse >= 0x80) && (addresse <= 0xff)) // RESET Mode ?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -