⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sja1000.c

📁 canbus4linux,来自www.sourceforge.net
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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_LICENSEMODULE_LICENSE("GPL");#endifint 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 10static 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 + -