📄 intel82527_can.c
字号:
{
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 + -