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

📄 sja1000.c

📁 在linux2.6.14下的can的驱动
💻 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_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 + -