📄 main.c
字号:
printk("can busy \n");
return -BUSY;
}
dev->status=read_status(dev->base_addr);
if (test_and_clear_bit(15,&dev->status)) {
printk("CAN RESET\n");
return -RESET;
}
if (test_and_clear_bit(6,&dev->status)) {
printk("receive and send error >96\n");
return -E96;
}
if (test_and_clear_bit(7,&dev->status)) {
printk("bus off\n");
return -BUSOFF;
}
temp=tx_message(send_buf,dev->base_addr,count);
if (temp!=count) {
if (!(test_and_clear_bit(0,&dev->tx_lock))) {
printk("unkonwn lock error \n");
return -ELOCK;
}
else {
printk("error send %d \n",count-temp);
return temp;
}
}
if (!(test_and_clear_bit(0,&dev->tx_lock))) {
printk("unkonwn lock error \n");
return -ELOCK;
}
return count;
}
struct file_operations CAN_fops = { //If we use this type , needn't to use NULL //to fill the position of every NULL operate
read: CAN_read,
write: CAN_write,
poll: CAN_poll,
ioctl: CAN_ioctl, //220
open: CAN_open,
release: CAN_release,
fasync: CAN_fasync,
};
/**********************************************************/
/* First , the function's implement is by reading the parm of the file at (/etc/
* sbscan.conf, but this use is not very good, so we set it in the function
*/
int read_parm()
{
int i;
for(i=0; i<CAN_DEV_NUM; i++){
/*******************************************************************************
* Now, Do NOTICE tha remap the device's address to virtual address while init
* the device.
*
*******************************************************************************/
addr[i] = (int)ioremap(addr[i], 4096);
}
return 0;
}
int set_config()
{
struct CAN_init_struct * CAN_init;
int i,triggerlevel=1;
if (read_parm()) {
printk("invalid base address or irq \n");
return -1;
}
for (i=0;i<CAN_DEV_NUM;i++) {
if (!(CAN_device[i]= (struct CAN_device_struct *)kmalloc(sizeof(struct CAN_device_struct),GFP_KERNEL))) {
printk("<1>allocate mem failed\n");
return -ENOMEM;
}
memset(CAN_device[i],0,sizeof(struct CAN_device_struct));
if (!(CAN_init=(struct CAN_init_struct *)kmalloc(sizeof(struct CAN_init_struct),GFP_KERNEL))) {
printk("<1>allocate mem failed\n");
return -ENOMEM;
}
memset(CAN_init,0,sizeof(struct CAN_init_struct));
CAN_init->filter=SINGLE;
CAN_init->lis_on=LOFF;
CAN_init->test=TOFF;
CAN_init->sleep=SOFF;
CAN_init->baud_rate=B1000;
CAN_init->trig_level=triggerlevel;
CAN_init->code1=0x1+i;
CAN_init->code2=0x1+i;
CAN_init->code3=0x1+i;
CAN_init->code4=0x1+i;
CAN_init->mask1=0xff;
CAN_init->mask2=0xff;
CAN_init->mask3=0xff;
CAN_init->mask4=0xff;
CAN_device[i]->dev_name=DEVNAME[i];
CAN_device[i]->major=CAN_major;
CAN_device[i]->minor=i;
CAN_device[i]->parm=CAN_init;
/*The next two lines is modified by useing the new varible*/
CAN_device[i]->base_addr=addr[i]; //320
CAN_device[i]->int_level=cirq[i];
CAN_device[i]->recv_data=(struct CAN_frame *)get_free_page(GFP_KERNEL);
if (!CAN_device[i]->recv_data) {
printk("no memem");
return -ENOMEM;
}
CAN_device[i]->recv_bottom_task=(struct tq_struct *)kmalloc(sizeof(struct tq_struct),GFP_KERNEL);
if (!CAN_device[i]->recv_bottom_task) {
printk("no memem\n");
return -ENOMEM;
}
memset(CAN_device[i]->recv_bottom_task,0,sizeof(struct tq_struct));
CAN_device[i]->recv_bottom_task->routine=recv_bottom_half;
CAN_device[i]->recv_bottom_task->data=(void *)CAN_device[i];
CAN_device[i]->recv_head=CAN_device[i]->recv_tail=0;
}
return 0;
}
int init_board()
{
int i,result;
int retry;
unsigned long flags;
save_flags(flags);
cli();
for (i=0;i<CAN_DEV_NUM;i++) {
#ifdef DEBUG
printk("<1>CAN%d->base_addr = %08x\n", i, CAN_device[i]->base_addr);
#endif
save_flags(flags);
cli();
reset_CAN(CAN_device[i]->base_addr);
udelay(3000);
if (!(result=read_version(CAN_device[i]->base_addr))) {
printk("CAN hardware version error!\n");
return -1;
}
else
printk("hardware version %d\n",result);
set_trig_level(CAN_device[i]->parm->trig_level,CAN_device[i]->base_addr);
init_global(*CAN_device[i]->parm,CAN_device[i]->base_addr);
restore_flags(flags);
retry=3;
do {
CAN_device[i]->status=read_status(CAN_device[i]->base_addr);
printk("<1>Now the status:%08x\n", CAN_device[i]->status);
udelay(3000);
} while ((CAN_device[i]->status)&&(retry--));
if (CAN_device[i]->status) {
printk("CAN%d init error\n",i);
return -1;
}
CAN_device[i]->rx_lock=0;
CAN_device[i]->tx_lock=0;
/*****************************************************************************
* At the old realease 2.2.x, the initalization is often use the mode
* *
* CAN_device[i]->recv_queue=NULL; *
* CAN_device[i]->send_queue=NULL; *
* and in the new realease 2.4.x, this mode is not needed *
*********************************************************************************/
init_waitqueue_head(&CAN_device[i]->recv_queue);
init_waitqueue_head(&CAN_device[i]->send_queue);
CAN_device[i]->ref_count=0;
CAN_device[i]->CAN_timer=
(struct timer_list *)kmalloc(sizeof(struct timer_list),GFP_KERNEL);
CAN_device[i]->CAN_timer->data=0;
CAN_device[i]->CAN_timer->function=timer_function;
CAN_device[i]->CAN_timer->expires=0;
init_timer(CAN_device[i]->CAN_timer);
CAN_device[i]->timer_count=0;
reset_base_addr(CAN_device[i]->base_addr);
}
return 0;
}
/******************************************************************************* * The 2.4.x realease often use the new type to define the function "init_module * " and the function "cleanup_module", but now, we use like below, and which we * should notice to include the head file "init.h"
*/
#if LINUX_VERSION_CODE > VERSION_CODE(2,4,0)
static void __exit CAN_cleanup_module(void)
#else
void cleanup_module(void)
#endif
{
if (unregister_chrdev(CAN_major,"sbs_can"))
printk("clean modules failed\n");
}
#if LINUX_VERSION_CODE > VERSION_CODE(2,4,0)
static int __init CAN_init_module(void)
#else
int init_module(void)
#endif
{
int result;
printk("<1> \n");
printk("<1> Linux driver 1.0 for SBS SysExpanModle(TM)/CSM\n");
printk("<1> Copyright (c) 2001 SBS Science&Technology Co.,Ltd \n\n");
EXPORT_NO_SYMBOLS;
if (set_config()) { //ioremap ->addr[];kmalloc ->CAN_device[];initial CAN_device[]
printk("set_config error\n");
return -1;
}
if (init_board()) { //cli()->reset_CAN->read_version->set_trig_level->init_global->read_status
//->init_waitqueue_head->CAN_timer
printk("Initial CAN board failed\n");
return -1;
}
if ((result = register_chrdev(CAN_major, "sbs_can", &CAN_fops))<0) {
printk(KERN_INFO "CAN: can't get major number\n");
return result;
}
return 0;
}
#if LINUX_VERSION_CODE > VERSION_CODE(2,4,0)
module_init(CAN_init_module); //Two macros at the 2.4.x kernel
module_exit(CAN_cleanup_module);
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -