📄 smartcan.c
字号:
/* smartcan.c
* Linux CAN-bus device driver.
* Written by Arnaud Westenberg email:arnaud@wanadoo.nl
* This software is released under the GPL-License.
* Version 0.7 6 Aug 2001
*/
#include <linux/autoconf.h>
#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
#define MODVERSIONS
#endif
#if defined (MODVERSIONS)
#include <linux/modversions.h>
#endif
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/irq.h>
#include "sysdep.h"
#include "candrv.h"
#include "smartcan.h"
#include "i82527.h"
int smartcan_irq=-1;
unsigned long smartcan_base=0x0;
int smartcan_request_io(unsigned long io_addr)
{
int err=0;
if ( (err=check_region(io_addr,0x04)) < 0 ) {
CANMSG("Unable to open port: 0x%lx\n",io_addr);
return -ENODEV;
}
else {
request_region(io_addr,0x04,DEVICE_NAME);
DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + 0x04 - 1);
}
return 0;
}
int smartcan_release_io(unsigned long io_addr)
{
release_region(io_addr,0x04);
return 0;
}
int smartcan_reset(int card)
{
int i=0;
DEBUGMSG("Resetting smartcan hardware ...\n");
outb(0x00,candevices_p[card]->res_addr);
while (i < 1000000) {
i++;
outb(0x01,candevices_p[card]->res_addr);
}
outb(0x00,candevices_p[card]->res_addr);
/* Check hardware reset status */
i=0;
outb(candevices_p[card]->io_addr+iCPU,candevices_p[card]->io_addr);
while ( (inb(candevices_p[card]->io_addr+1)&0x80) && (i<=15) ) {
udelay(20000);
i++;
}
if (i>=15) {
CANMSG("Reset status timeout!\n");
CANMSG("Please check your hardware.\n");
return -ENODEV;
}
else
DEBUGMSG("Chip0 reset status ok.\n");
return 0;
}
int smartcan_init_hw_data(int card)
{
candevices_p[card]->res_addr=candevices_p[card]->io_addr+0x02;
candevices_p[card]->nr_82527_chips=1;
candevices_p[card]->nr_sja1000_chips=0;
return 0;
}
int smartcan_init_chip_data(int card, int chipnr)
{
candevices_p[card]->chip[chipnr]->chip_type="i82527";
candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
candevices_p[card]->chip[chipnr]->clock = 16000000;
candevices_p[card]->chip[chipnr]->int_cpu_reg = iCPU_DSC;
candevices_p[card]->chip[chipnr]->int_clk_reg = iCLK_SL1;
candevices_p[card]->chip[chipnr]->int_bus_reg = iBUS_CBY;
candevices_p[card]->chip[chipnr]->sja_cdr_reg = 0;
candevices_p[card]->chip[chipnr]->sja_ocr_reg = 0;
smartcan_irq=candevices_p[card]->chip[chipnr]->chip_irq;
smartcan_base=candevices_p[card]->chip[chipnr]->chip_base_addr;
return 0;
}
int smartcan_init_obj_data(int chipnr, int objnr)
{
chips_p[chipnr]->msgobj[objnr]->obj_base_addr=(objnr+1)*0x10;
chips_p[chipnr]->msgobj[objnr]->flags=0;
return 0;
}
void smartcan_write_register(unsigned char data, unsigned long address)
{
disable_irq(smartcan_irq);
outb(address-smartcan_base,smartcan_base);
outb(data,smartcan_base+1);
enable_irq(smartcan_irq);
}
unsigned smartcan_read_register(unsigned long address)
{
unsigned ret;
disable_irq(smartcan_irq);
outb(address-smartcan_base,smartcan_base);
ret=inb(smartcan_base+1);
enable_irq(smartcan_irq);
return ret;
}
int smartcan_program_irq(int card)
{
CANMSG("The 'smartcan' card doesn't have programmable interrupts\n");
return 0;
}
/* !!! Don't change this function !!! */
int smartcan_register(struct hwspecops_t *hwspecops)
{
hwspecops->request_io = smartcan_request_io;
hwspecops->release_io = smartcan_release_io;
hwspecops->reset = smartcan_reset;
hwspecops->init_hw_data = smartcan_init_hw_data;
hwspecops->init_chip_data = smartcan_init_chip_data;
hwspecops->init_obj_data = smartcan_init_obj_data;
hwspecops->write_register = smartcan_write_register;
hwspecops->read_register = smartcan_read_register;
hwspecops->program_irq = smartcan_program_irq;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -