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

📄 intel82527_can.c

📁 intel 82527控制器描述can2.0协议的内容
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <linux/module.h>

#if defined(CONFIG_SMP)
#define __SMP__
#endif
 
#if defined(CONFIG_MODVERSIONS)
#define MODVERSIONS
#include <linux/modversions.h>
#endif
 
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/timer.h>        /* for timers */
#include <linux/fs.h>           /* file modes and device registration */
#include <linux/poll.h>         /* for poll */
#include <linux/wrapper.h>      /* mem_map_reserve,mem_map_unreserve */
#include <linux/proc_fs.h>
#include <linux/sysctl.h>
#include <linux/init.h>
#include <asm/io.h>

#include "intel82527_can.h"

/* module parameters and descriptions */
MODULE_PARM(ican_name, "s");
MODULE_PARM_DESC(ican_name, "Name of device");
 
MODULE_PARM(ican_debug, "1b");
MODULE_PARM_DESC(ican_debug, "Enable debugging messages");
 
MODULE_DESCRIPTION("ican, Sample character driver");
MODULE_AUTHOR("grd");

MODULE_LICENSE("GPL");

struct file_operations ican_fops = 
{
  read:    ican_read,
  write:   ican_write,
  ioctl:   ican_ioctl,
  open:	 	 ican_open,
  release: ican_release,
  poll:    ican_poll,
  owner:   THIS_MODULE,
};

DECLARE_WAIT_QUEUE_HEAD(inq);
DECLARE_WAIT_QUEUE_HEAD(outq);

static void i82527_start_chip(CAN_Dev *dev)
{
	unsigned short flags = 0;
	unsigned char* base;
	base=dev->reg_base;
	flags =readb(base+iCTL) & (iCTL_IE|iCTL_SIE|iCTL_EIE);
	writeb(flags,base+iCTL);
}

static void i82527_stop_chip(CAN_Dev *dev)
{
	unsigned short flags = 0;
	unsigned char* base;
	base=dev->reg_base;
	flags =readb(base+iCTL) & (iCTL_IE|iCTL_SIE|iCTL_EIE);
	writeb(flags|(iCTL_CCE|iCTL_INI),base+iCTL);
}

static void i82527_reset_chip(CAN_Dev *dev)
{
	int i=0,j=0,k=0;
	unsigned char* base;
	base=dev->reg_base;
	
	/***************** register reset *******************/
	writeb((iCTL_CCE | iCTL_INI),base+iCTL);// control register
	
	writeb(0,base+iSTAT);//status reister
	
	writeb((iCPU_DMC | iCPU_DSC | iCPU_CEN),base+iCPU);//CPU interface
	
	//writeb(0,base+iHSR);//High Speed Read

	writeb((iCLK_SL1 | iCLK_CD1),base+iCLK);//Clock Out Register
	
	writeb((iBUS_CBY),base+iBUS);//Bus Configuration Register
	
	readb(base+iIRQ);//interrupt register
	
	/**************** Write test pattern ********************/
	writeb(0x25,base+16+iMSGDAT0);
	writeb(0x52,base+32+iMSGDAT3);
	writeb(0xc3,base+160+iMSGDAT6);
	
	if(readb(base+16+iMSGDAT0)!=0x25 ||
		 readb(base+32+iMSGDAT3)!=0x52 ||
		 readb(base+160+iMSGDAT6)!=0xc3)
	{
		printk("Could not read back from the hardware.\n");
		printk("This probably means that your hardware is not correctly configured!\n");
		return -1;
	}
	else
	{
		printk("Could read back, hardware is probably configured correctly");
	}

	/*************** clear message object **********************/
	for(i=1;i<16;i++)
	{
		writeb(INTPD_RES | RXIE_RES | TXIE_RES | MVAL_RES,base+16*i+iMSGCTL0);
		writeb(NEWD_RES | MLST_RES | TXRQ_RES | RMPD_RES,base+16*i+iMSGCTL1);
		
		for(j=0;j<4;j++)
		{
			writeb(0,base+16*i+iMSGID0+j);
		}
		
		for(k=0;k<8;k++)
		{
			writeb(0,base+16*i+iMSGDAT0+j);
		}
		
		writeb(0,base+16*i+iMSGCFG);
	}
	
	/****************** set timing **************************/
	writeb((uint8_t) iCanTiming[9][0],base+iBT0);//Bit Timing Register
	writeb((uint8_t) iCanTiming[9][1],base+iBT1);
	
	/****************** set mask ****************************/ 
	writeb(0,base+iSGM0);//Standard Global Mask
	writeb(0,base+iSGM1);
	
	writeb(0,base+iEGM0);//Extended Global Mask
	writeb(0,base+iEGM1);
	writeb(0,base+iEGM2);
	writeb(0,base+iEGM3); 
	
	writeb(0,base+i15M0);//Message 15 Mask
	writeb(0,base+i15M1);
	writeb(0,base+i15M2);
	writeb(0,base+i15M3);
}

static int ican_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
	unsigned char* base;
	CAN_Dev *dev;
	int myarg;
	int err=0;
	int i=0;
	
	int dev_minor = MINOR(inode->i_rdev) & 0x0f;
	
	base = canDev[dev_minor].reg_base;
		
	dev = canDev + dev_minor;
	
	get_user(myarg, (int *)arg);
	
	if(_IOC_TYPE(cmd) != ICAN_IOC_BASE)
	{
		return -EINVAL;
	}
	if(_IOC_NR(cmd) > CAN_IOC_MAXNR)
	{
		return -EINVAL;
	}
	
	if(_IOC_DIR(cmd) & _IOC_READ)
	{
		err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
	}
	else if(_IOC_DIR(cmd) & _IOC_WRITE)
	{
		err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
	}
	if(err)
	{
		return -EFAULT;
	}
	
	switch(cmd)
	{
		case ICAN_IOC_SBAUD:
			{
				if((arg >= 0) && (arg <= 9))
				{
					i82527_stop_chip(dev);
					writeb(iCanTiming[arg][0],base+iBT0);
					writeb(iCanTiming[arg][1],base+iBT1);
					i82527_start_chip(dev);
				}
			}
			break;
		case ICAN_IOC_MASK:
			{
				//none
			}
			break;
		case ICAN_IOC_CRBUF:
			{
				dev->nm_rb = 0;			               
				dev->wp_rb = 0;
				dev->rp_rb =0;
			}
			break;
		case ICAN_IOC_CWBUF:
			{
				dev->nm_wb = 0;		
				dev->wp_wb = 0;	
				dev->rp_wb =0;
			}
			break;
		case ICAN_IOC_RREG:
			{
				if(myarg>=0x100)
				{
					printk("Error reister number\n");
				}
				else
				{
					printk("0x%x is 0x%x\n",myarg,readb(base+myarg));
				}
			}
			break;
		case ICAN_IOC_RTTS:
			{
				copy_to_user((struct timeval *)arg, &transmit_timestamp, sizeof(struct timeval));
			}
			break;
		case ICAN_IOC_RAPS:
			{
				printk("Ican active_passive_status is %d\n",dev->active_passive_status);
			}
			break;
		case ICAN_IOC_SBTR:
			{
				i82527_stop_chip(dev);
				writeb((arg >> 8) & 0xff,base+iBT0);
				writeb(arg & 0xff,base+iBT1);
				i82527_start_chip(dev);
			}
			break;
		case ICAN_IOC_START:
			{
				i82527_start_chip(dev);
			}
			break;
		case ICAN_IOC_STOP:
			{
				i82527_stop_chip(dev);
			}
			break;
		case ICAN_IOC_RESET:
			{
				i82527_reset_chip(dev);
			}
			break;
		case ICAN_IOC_CONF_FILTER:
			{
				//none
			}
			break;
		case ICAN_IOC_SEND:
			{
				//none
			}
			break;
		case ICAN_IOC_RECEIVE:
			{
				//none
			}
			break;
		default:
			{
				return -EINVAL;
			}
			break;
	}
	return 0;
}

static unsigned int ican_poll(struct file *filp, poll_table *wait)
{
	unsigned int mask = 0;

	CAN_Dev *dev = filp->private_data;

	poll_wait(filp, &inq, wait);
	poll_wait(filp, &outq, wait);

	if(dev->nm_rb > 0)  /* at least one message in the buffer */
		mask |= POLLIN | POLLRDNORM;  /* readable */

	if(dev->nm_wb < BUFFER_SIZE)  /* at least one message in the buffer */
		mask |= POLLOUT | POLLWRNORM;  /* readable */

	return mask;
}

static void read_from_INTEL82527(CAN_Dev *dev)
{
	int i = 0;
  uint8_t msgctlreg;
  uint8_t ctl1reg;
  
  uint8_t id0, id1, id2, id3;
	unsigned char* base;
	
	base=dev->reg_base;
	
	ctl1reg=readb(base+16*15+iMSGCTL1);
	
	if(dev->nm_rb < BUFFER_SIZE)
	{
		if( ctl1reg & MLST_SET )
		{
			printk("\ni82527: Previous message lost\n");
		}
	
		if(ctl1reg & NEWD_SET)
		{
			if (ctl1reg & RMPD_SET) 
			{
       	dev->read_buf[dev->wp_rb].rtr=1;
    	}
    
   	 	msgctlreg=readb(base+16*15+iMSGCFG);
    
    	if( msgctlreg & MCFG_XTD ) 
    	{
      	id0=readb(base+16*15+iMSGID3);
      	id1=readb(base+16*15+iMSGID2)<<8;
      	id2=readb(base+16*15+iMSGID1)<<16;
      	id3=readb(base+16*15+iMSGID0)<<24; 
      	dev->read_buf[dev->wp_rb].type=EXTENDED;
     	  dev->read_buf[dev->wp_rb].id=(id0|id1|id2|id3)>>3;    
    	}
    	else
    	{
    		id0=readb(base+16*15+iMSGID1);
    		id1=readb(base+16*15+iMSGID0)<<8;
    		dev->read_buf[dev->wp_rb].type=STANDARD;
      	dev->read_buf[dev->wp_rb].id=(id0|id1|id2|id3)>>5;
    	}
    
    	msgctlreg  &= 0xf0;
    	msgctlreg  = msgctlreg >>4;
    
    	msgctlreg %= 9;
    	dev->read_buf[dev->wp_rb].len=msgctlreg;
    
    	for (i = 0; i < msgctlreg; i++) 
    	{
    		dev->read_buf[dev->wp_rb].d[i]=readb(base+16*15+iMSGDAT0+i);
    	}
    
    	do_gettimeofday(&dev->read_buf[dev->wp_rb].timestamp);
    	transmit_timestamp=dev->read_buf[dev->wp_rb].timestamp;
    
    	writeb(MVAL_SET | TXIE_RES | RXIE_SET | INTPD_RES,base+16*15+iMSGCTL0);
    	writeb(RMPD_RES | TXRQ_RES | MLST_RES |  NEWD_RES,base+16*15+iMSGCTL1);
    	
    	dev->nm_rb++;
			dev->wp_rb++; 
			wake_up_interruptible(&inq);
		}
	}
	else
	{
		printk("CAN: buffer full, dropping message,this meassage will be release!\n");
	}
}

static ssize_t ican_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
	int pos, nmrb;
	CAN_Dev *dev = (CAN_Dev *)filp->private_data;
	
	pos = dev->rp_rb;
  nmrb = dev->nm_rb; 
	
	if(nmrb == 0)
	{
		if(filp->f_flags & O_NONBLOCK)
		{ 
			return -EAGAIN;	
		}

		printk("\n can_read! sleep_on inq\n");
		interruptible_sleep_on(&inq); 

		if(signal_pending(current))
    {   printk("\n signal_pending \n");
			return -ERESTARTSYS;
    }
	}
	
	if(nmrb > 0)
	{
		copy_to_user(buf, &dev->read_buf[pos],MSG_LENGTH); 
		dev->nm_rb--;
		dev->rp_rb++;

		if(dev->rp_rb == dev->wp_rb)
		{		/* Buffer empty */
			dev->rp_rb = 0;
			dev->wp_rb = 0;
		}

		return MSG_LENGTH;
	}
	else
	{
		printk("No messages available nmrb=0x%x",nmrb);
		return -EAGAIN;	
	}			    
}

void ican_msgobj15_read_interrupt(CAN_Dev *dev)
{
	read_from_INTEL82527(dev);
}

void ican_msgobj_write_interrupt(CAN_Dev *dev)
{
	int i=1,j=0;
	uint8_t id0, id1, id2, id3;
	unsigned long flags;
	unsigned char* base;
	
	base=dev->reg_base;
	
	save_flags(flags);
	
	if(dev->nm_wb > 0)
	{
		writeb(RMPD_RES | TXRQ_RES | CPUU_SET | NEWD_SET,base+16+iMSGCTL1);
		writeb(MVAL_SET | TXIE_SET | RXIE_RES | INTPD_RES,base+16+iMSGCTL0);
		
		dev->write_buf[dev->rp_wb].len%=9;
		
		if(dev->write_buf[dev->rp_wb].type == EXTENDED)
		{
			writeb(dev->write_buf[dev->rp_wb].len<<4 | ( MCFG_DIR | MCFG_XTD ),base+16+iMSGCFG);
			id0=dev->write_buf[dev->rp_wb].id << 3;
			id1=dev->write_buf[dev->rp_wb].id >> 5;
			id2=dev->write_buf[dev->rp_wb].id >> 13;
			id3=dev->write_buf[dev->rp_wb].id >> 21;
			writeb(id3,base+16+iMSGID0);
			writeb(id2,base+16+iMSGID1);
			writeb(id1,base+16+iMSGID2);
			writeb(id0,base+16+iMSGID3);
		}
		else
		{
			writeb(dev->write_buf[dev->rp_wb].len<<4 | ( MCFG_DIR),base+16+iMSGCFG);
			id0=dev->write_buf[dev->rp_wb].id << 5;
			id1=dev->write_buf[dev->rp_wb].id >> 3;
			writeb(id1,base+16+iMSGID0);
			writeb(id0,base+16+iMSGID1);
		}
		
		for ( j=0; j <dev->write_buf[dev->rp_wb].len ; j++ ) 
		{
       writeb( dev->write_buf[dev->rp_wb].d[i],base+16+iMSGDAT0+j);
    }
    
    if (dev->write_buf[dev->rp_wb].rtr == REMOTEFRAME)
		{
       writeb(RMPD_RES | TXRQ_RES | CPUU_RES | NEWD_UNC,base+16+iMSGCTL1);
    }
    else 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -