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

📄 intel82527_can.c

📁 intel 82527控制器描述can2.0协议的内容
💻 C
📖 第 1 页 / 共 2 页
字号:
    {
       writeb(RMPD_RES | TXRQ_SET | CPUU_RES | NEWD_UNC,base+16+iMSGCTL1);
    }
    
    dev->nm_wb--;
		dev->rp_wb++;
		
		if(dev->rp_wb == dev->wp_wb)
		{	
				dev->rp_wb = 0;
				dev->wp_wb = 0;
		}
				
		writeb((MVAL_UNC | TXIE_UNC | RXIE_UNC | INTPD_RES),base+16+iMSGCTL0);
	}	
	restore_flags(flags);
	wake_up_interruptible(&outq); 
}

void ican_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	unsigned char* base;
	int minor= *(int *) dev_id;	
	CAN_Dev *dev=canDev +minor;
	uint8_t irqreg;
  uint8_t lastIrqreg;
	
	base=canDev[minor].reg_base;
	irqreg=readb(base+iIRQ);
	
	lastIrqreg=irqreg;
	
	while(irqreg)
	{
		switch(irqreg)
		{
			case 1:
			{
				uint8_t status;
				
				status=readb(base+iSTAT);
				writeb(0,base+iSTAT);
				
				if ( status & iSTAT_RXOK )
				{
					writeb(status & ~iSTAT_RXOK,base+iSTAT);
					printk("\niSTAT_RXOK\n");
				}
				
				if ( status & iSTAT_TXOK ) 
				{
					writeb(status & ~iSTAT_TXOK,base+iSTAT);
					printk("\niSTAT_TXOK\n");
				}
				
				if ( status & iSTAT_WARN ) 
				{
					dev->active_passive_status = PASSIVE;
					printk("\nBus step into passive\n");
				}
				
				if ( status & iSTAT_WAKE )
				{
					printk("\nBus waked\n");
				}
				
				if ( status & iSTAT_BOFF )
				{
					long myflags;
					
					dev->active_passive_status = BUSOFF;
										
					myflags = readb(base+iCTL) | ( iCTL_IE | iCTL_EIE );
					myflags &= ~iCTL_INI;
					writeb(myflags,base+iCTL);
					
					printk("\nBus off\n");
				}
				
				if ( status & Stuff_Error )
				{
					printk("\nStuff_Error\n");
				}
				
				if ( status & Form_Error )
				{
					printk("\nForm_Error\n");
				}
				
				if ( status & Ack_Error )
				{
					printk("\nAck_Error\n");
				}
				
				if ( status & Bit1_Error )
				{
					printk("\nBit1_Error\n");
				}
				
				if ( status & Bit0_Error )
				{
					printk("\nBit0_Error\n");
				}
				
				if ( status & CRC_Error )
				{
					printk("\nCRC_Error\n");
				}
				
				if ( ( status & No_Error ) || ( status & Unused ) )
				{
					printk("\nThis condition can never happen\n");
				}
			}
			break;
			case 2:
			{
				ican_msgobj15_read_interrupt(dev);
			}
			break;
			case 3:
			{
				ican_msgobj_write_interrupt(dev);
			}
			break;
			case 4:
			{
				
			}
			break;
			default :
			{
				printk("Unexpected i82527_CAN_Interrupt: irqreq=0x%X\n", irqreg);
			}
			break;
		}
		
		irqreg=readb(base+iIRQ);
		
		if (irqreg == lastIrqreg)
    {          
       printk("i82527_CAN_Interrupt: irqreq repeated!!!! 0x%X\n", irqreg);
    }
    lastIrqreg =irqreg;
	}	
}

static void write_to_INTEL82527(CAN_Dev *dev)
{
	int i=0,j=0;
	uint8_t id0, id1, id2, id3;
	unsigned char* base;
	
	base=dev->reg_base;
		
	if(dev->nm_wb > 0)
	{
		//for(i=1;i<15;i++)
		{
			i=1;
			dev->write_buf[dev->rp_wb].len%=9;
			if((readb(base+16*i+iMSGCTL1) & TXRQ_UNC)==TXRQ_SET)
			{
				writeb(RMPD_RES | TXRQ_RES | CPUU_SET | NEWD_SET,base+16*i+iMSGCTL1);
			  writeb(MVAL_SET | TXIE_SET | RXIE_RES | INTPD_RES,base+16*i+iMSGCTL0);
				if(dev->write_buf[dev->rp_wb].type == EXTENDED)
				{
					writeb(dev->write_buf[dev->rp_wb].len<<4 | ( MCFG_DIR | MCFG_XTD ),base+16*i+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*i+iMSGID0);
					writeb(id2,base+16*i+iMSGID1);
					writeb(id1,base+16*i+iMSGID2);
					writeb(id0,base+16*i+iMSGID3);
				}
				else
				{
					writeb(dev->write_buf[dev->rp_wb].len<<4 | ( MCFG_DIR),base+16*i+iMSGCFG);
					id0=dev->write_buf[dev->rp_wb].id << 5;
					id1=dev->write_buf[dev->rp_wb].id >> 3;
					writeb(id1,base+16*i+iMSGID0);
					writeb(id0,base+16*i+iMSGID1);
				}
				
				for ( j=0; j <dev->write_buf[dev->rp_wb].len ; j++ ) 
				{
        	writeb( dev->write_buf[dev->rp_wb].d[i],base+16*i+iMSGDAT0+j);
    		}
    		
    		if (dev->write_buf[dev->rp_wb].rtr == REMOTEFRAME)
				{
        	writeb(RMPD_RES | TXRQ_RES | CPUU_RES | NEWD_UNC,base+16*i+iMSGCTL1);
    		}
    		else 
    		{
       	 	writeb(RMPD_RES | TXRQ_SET | CPUU_RES | NEWD_UNC,base+16*i+iMSGCTL1);
    		}
			}
		}
		
		dev->nm_wb--;
		dev->rp_wb++;
		
		if(dev->rp_wb == dev->wp_wb)
		{	
				dev->rp_wb = 0;
				dev->wp_wb = 0;
		}
		
		writeb((MVAL_UNC | TXIE_UNC | RXIE_UNC | INTPD_RES),base+16+iMSGCTL0);
		wake_up_interruptible(&outq); 
	}
}

static ssize_t ican_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
	int pos, nmwb;
	CAN_Dev *dev = filp->private_data;
	
	pos = dev->wp_wb;
	nmwb = dev->nm_wb;
	
	if(nmwb == BUFFER_SIZE)
	{ 
		if(filp->f_flags & O_NONBLOCK)
		{
			return -EAGAIN;		         
		}
		printk("\ncan_write:sleep\n");
		interruptible_sleep_on(&outq); 

		if(signal_pending(current))
			return -ERESTARTSYS;
	}
	
	if(nmwb < BUFFER_SIZE)
	{	
		copy_from_user(&dev->write_buf[pos], buf, MSG_LENGTH);	
		dev->nm_wb++;
		dev->wp_wb++;
		
		write_to_INTEL82527(dev);
		return MSG_LENGTH;
	}
	else
	{
		return -EAGAIN;
	}
}

static int ican_open(struct inode *inode, struct file *filp)
{
	int i=0,j=0,k=0,result;
	unsigned char * base;
	CAN_Dev *dev;
	
	unsigned int minor=MINOR(inode->i_rdev);
	
	printk("\nIcan opening\n");
	
	if(minor>=CAN_NUMBER)
	{
		printk("CAN: Illegal minor number %d\n", minor);
		return -EINVAL;
	}	
	
	dev = canDev + minor;
	filp->private_data = dev;
	
	if(dev->isopen>0)
	{
		printk("\nDevice already opened\n");
		return -EBUSY;
	}
	dev->isopen++;
	
	base=canDev[minor].reg_base;
	
	/**************** regist irq ****************************/
	result = request_irq(IRQ_NUM, ican_interrupt, SA_SHIRQ, "ican", NULL);
	if(result)
	{
		printk(KERN_INFO "CAN: can't get assigned IRQ%d\n", IRQ_NUM);
		return -EBUSY;
	}
	else
	{
		printk("can%x get assigned IRQ%d\n",minor, IRQ_NUM);
	}
	
	/****************** init buffer *******************/
	dev->nm_rb = 0;    /* 0 messages in the read buffer */
	dev->wp_rb = 0;    /* initial write position in the read buffer */
	dev->rp_rb =0;     /* initial read position in the read buffer */

	dev->nm_wb = 0;    /* 0 messages in the write buffer */
	dev->wp_wb = 0;    /* initial write position in the write buffer */
	dev->rp_wb =0;  
	
	/****************** init mode *********************/
	dev->frame_mode = EXTENDED;
	
	/***************** bus status *********************/
	dev->active_passive_status = ACTIVE;
	
	/***************** baud rate **********************/
	dev->baud_rate = 1000;
	
	/***************** register set *******************/
	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);
	
	/******************* start chip work ***************************/
	RxErr[minor] = 0;
  TxErr[minor] = 0;
  
  readb(base+iIRQ);
  writeb(0,base+iSTAT);
  
  
  writeb((NEWD_RES | MLST_RES | TXRQ_RES | RMPD_RES),base+16*15+iMSGCTL1);
  writeb((MVAL_SET | TXIE_RES | RXIE_SET | INTPD_RES),base+16*15+iMSGCTL0);
  
  //Can_SetMask
  writeb(MCFG_XTD,base+16*15+iMSGCFG);
  
  writeb((RMPD_RES | TXRQ_RES | CPUU_RES | NEWD_RES),base+16+iMSGCTL1);
  writeb((MVAL_RES | TXIE_RES | RXIE_RES | INTPD_RES),base+16+iMSGCTL0);
  
	writeb(( iCTL_IE | iCTL_EIE),base+iCTL);
	
	MOD_INC_USE_COUNT;
	printk("\nican_open\n");
	return 0;
}

static int ican_release(struct inode *inode, struct file *filp)
{
	CAN_Dev *dev = (CAN_Dev *)filp->private_data;
	unsigned char* base;
	
	int minor = MINOR(inode->i_rdev);
	base = canDev[minor].reg_base;
	
	writeb((iCTL_CCE | iCTL_INI),base+iCTL);
	readb(base+iIRQ);
	writeb(0,base+iSTAT);
	
	free_irq(IRQ_NUM, NULL);
	
	if(dev->isopen>0)
	{
		--dev->isopen;
	}
	
	MOD_DEC_USE_COUNT;
	printk("\nican_release\n");
	return 0;
}

int ican_init(void)
{
	int result;
	
	printk("\nican_init \n");
	
	int_reg=ioremap (INT_REG,0x1);
	
	result = register_chrdev(CAN_MAJOR, "ican", &ican_fops);
	if(result<0)
	{
		printk("CAN: Couldn't register can driver\n");
		goto fail;
	}
	
	canDev[0].reg_base = 	ioremap(REGBASE1,IO_RANGE);	
	canDev[1].reg_base = 	ioremap(REGBASE2,IO_RANGE);
	printk("first sja1000 base address:  0x%x\n",canDev[0].reg_base);
	printk("second sja1000 base address: 0x%x\n",canDev[1].reg_base);
	
	canDev[0].isopen = 0;
	canDev[1].isopen = 0;
	
	return result;
	
	fail:
		printk("\nican device init failed\n");
	
	return -EBUSY;
}

void ican_cleanup(void)
{
	unregister_chrdev(CAN_MAJOR, "ican");

	iounmap(canDev[0].reg_base);
	iounmap(canDev[1].reg_base);
	iounmap(int_reg);
	
	printk("\nican device unload\n");
}

module_init(ican_init);
module_exit(ican_cleanup);

⌨️ 快捷键说明

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