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

📄 main.c

📁 盛博can驱动程序功能很全
💻 C
📖 第 1 页 / 共 2 页
字号:
       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 + -