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

📄 mcpcan.c

📁 linux-2.6.12下的can总线mcp2510芯片的完整驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
static irqreturn_t mcpcan0_handler(int irq, void *dev_id, struct pt_regs *reg){	struct MCP_device *dev = dev_id;	struct mcpcan_data datagram;	int written;	char regvalue, regvalue2;	//struct mcpcan_data *datagramptr;  printk(KERN_ERR "hello,finally enter %s!!!!!!!!!!!!!!!!!!!!!!!!\n",__FUNCTION__);	printk(KERN_ERR "\rextern irq 8 handled\n");	regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTE)), ARG_UNUSED, ARG_UNUSED );	//printk("CANINTE = 0x%02x\n",regvalue);	regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED );	//printk("CANINTF = 0x%02x\n",regvalue);	if(regvalue & 0x01){		datagram.BufNo = RXBUF0;		MCP2510_RX(datagram.BufNo, &(datagram.IdType), &(datagram.id), &(datagram.DataLen), datagram.data );		//printk("RXBUF0\n");        //printk("datagram.BufNo = %d\n",datagram.BufNo);        //printk("datagram.IdType = %d\n",datagram.IdType);        //printk("datagram.id = %d\n",datagram.id);        //printk("datagram.DataLen = %d\n",datagram.DataLen);        //printk("datagram.data = %s\n",datagram.data);	    /* Write a 16 byte record. Assume BUF_SIZE is a multiple of 16 */		memcpy((void *)dev->RecvHead, &datagram, sizeof(struct mcpcan_data));		//datagramptr = (struct mcpcan_data *)dev->RecvHead;		//printk("RecvHead->BufNo = %d\n",datagramptr->BufNo);		//printk("RecvHead->IdType = %d\n",datagramptr->IdType);		//printk("RecvHead->id = %d\n",datagramptr->id);		//printk("RecvHead->DataLen = %d\n",datagramptr->DataLen);		//printk("RecvHead->data = %s\n",datagramptr->data);		incr_buffer_pointer(&(dev->RecvHead), sizeof(struct mcpcan_data), dev->MinorNum);		wake_up_interruptible(&(dev->inq)); /* awake any reading process */		CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x01, 0x00 );     //in fact already clear interrupt bit in RX 	}	if(regvalue & 0x02){		datagram.BufNo = RXBUF1;		//this function should be rewritten to receive datagram from RXB1??????????????????		MCP2510_RX(datagram.BufNo, &(datagram.IdType), &(datagram.id), &(datagram.DataLen), datagram.data );		//printk("RXBUF1\n");	    /* Write a 16 byte record. Assume BUF_SIZE is a multiple of 16 */		memcpy((void *)dev->RecvHead, &datagram, sizeof(struct mcpcan_data));				incr_buffer_pointer(&(dev->RecvHead), sizeof(struct mcpcan_data), dev->MinorNum);		wake_up_interruptible(&dev->inq); /* awake any reading process */		CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x02, 0x00 );     //in fact already clear interrupt bit in RX	}	if(regvalue & 0xe0){		printk("CAN error with CANINTF = 0x%02x.\n", regvalue);		if(regvalue & 0x80)printk("MERRF:message error.\n");		if(regvalue & 0x40)printk("WAKIF:wake up interrupt.\n");		if(regvalue & 0x20)printk("ERRIF:CAN bus error interrupt.\n");				regvalue2 = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->EFLG)), ARG_UNUSED, ARG_UNUSED );		printk("EFLG = 0x%02x.\n", regvalue2);                regvalue2 = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->TEC)), ARG_UNUSED, ARG_UNUSED );                printk("TEC = 0x%02x.\n", regvalue2);                regvalue2 = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->REC)), ARG_UNUSED, ARG_UNUSED );                printk("REC = 0x%02x.\n", regvalue2);		CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0xe0, 0x00 );	}	if(CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED ) & 0x1c){  //didn't open the 3 send interrupts		CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), 0x1c, 0x00 ); //clear TX bits directly(it will set 1,but no int)	}        regvalue = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED );	//printk("after interrupt processing, CANINTF = 0x%02x\n",regvalue);		return IRQ_HANDLED; //fla}static void mcpcan1_handler(int irq, void *dev_id, struct pt_regs *regs){	//printk("\rextern irq ? handled");}/*****************************MCPCAN open**********************************/static int device_open(struct inode *inode,struct file *filp){    int MinorNum;	int eint_irq;	int ret_val;    struct MCP_device *dev;	static int irqcount0=0, irqcount1=0;		//printk(KERN_ERR "hello,enter %s\n",__FUNCTION__);   // MinorNum = MINOR(inode->i_rdev);    MinorNum = iminor(inode);        if(MinorNum >= MCP_NUM) return(-ENODEV);            dev = Device[MinorNum];    filp->private_data = dev;        //save to private_data		//request_region(0x59000000,0x38,"MCPCAN");    //SPI interface	request_mem_region(0x59000000,0x38,"MCPCAN");		//request_region(0x56000000,0x94,"MCPCAN");  //I/O port	request_mem_region(0x56000000,0x94,"MCPCAN");		//request_region(0x4c00000c,4,"MCPCAN");  //clock   request_mem_region(0x4c00000c,4,"MCPCAN");	if(irqcount0 == 0){		eint_irq = IRQ_EINT11;				//now set extint for eint8 instead of the up line!s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_EINT11);writel(readl(S3C2410_INTMSK)& (~(1<<5)),S3C2410_INTMSK);writel(readl(eintmask)& (~(1<<11)),eintmask);writel(readl(S3C2410_EXTINT1)|(0x00007000)&(0xffffbfff),S3C2410_EXTINT1);s3c2410_gpio_pullup(S3C2410_GPG3,0); //disret_val = request_irq(eint_irq, mcpcan0_handler, SA_INTERRUPT | SA_SHIRQ, MCP_name[dev->MinorNum], dev);		if (ret_val < 0) {			return ret_val;		}		irqcount0++;	}	MCP2510_Init(MinorNum);printk(KERN_ERR "INTMSK = %08x\nEINTMASK = %08x\n\CLKCON = %08x\nSPCON0 = %08x\nGPECON = %08x\nGPGCON = %08x\n",readl(S3C2410_INTMSK),readl(eintmask),readl(S3C2410_CLKCON),readl(spcon0),readl(rGPECON),readl(rGPGCON));//	MOD_INC_USE_COUNT;    return 0;}/*****************************Functin MCP_release**************************/static int device_release(struct inode *inode,struct file *filp){	struct MCP_device *dev = filp->private_data;  //printk(KERN_ERR "hello,enter %s\n",__FUNCTION__);	release_region(0x59000000,0x38);	release_region(0x56000000,0x94);	release_region(0x4c00000c,4);	free_irq(dev->IrqNum,dev);    //shared irq	//MOD_DEC_USE_COUNT;	return 0;}ssize_t device_read (struct file *filp, char *buf, size_t count, loff_t *f_pos){	int count0;		struct MCP_device *dev = filp->private_data;	//printk(KERN_ERR "hello,enter %s\n",__FUNCTION__);	if (down_interruptible(&dev->sem))		return -ERESTARTSYS;	while (dev->RecvHead == dev->RecvTail) 	{ /* nothing to read */		up(&dev->sem); /* release the lock */		if (filp->f_flags & O_NONBLOCK)			return -EAGAIN; 		if (wait_event_interruptible(dev->inq, (dev->RecvHead != dev->RecvTail)))			{			return -ERESTARTSYS; /* signal: tell the fs layer to handle it */			}		/* otherwise loop, but first reacquire the lock */				if (down_interruptible(&dev->sem))			return -ERESTARTSYS;	}	/* ok, data is there, return something */	/* count0 is the number of readable data bytes */	count0 = dev->RecvHead - dev->RecvTail;	if (count0 < 0) /* wrapped */		count0 = dev->RecvBuf + BUF_SIZE - dev->RecvTail;	if (count0 < count) count = count0;	if (copy_to_user(buf, (char *)dev->RecvTail, count)){		up (&dev->sem);		return -EFAULT;	}	incr_buffer_pointer(&(dev->RecvTail), count, dev->MinorNum);	up (&dev->sem);	return count;}ssize_t device_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos){	mcpcan_data     temp;	//printk(KERN_ERR "hello,enter %s\n",__FUNCTION__);	struct MCP_device *dev = filp->private_data;	if(down_interruptible(&dev->sem))		return -ERESTARTSYS;	copy_from_user(&temp, buf, sizeof(struct mcpcan_data));        printk(KERN_ERR "hello,TX data in kernel is %s\n",temp.data);			MCP2510_TX(temp.BufNo,temp.IdType,temp.id,temp.DataLen,temp.data );	up(&dev->sem);       	return count;}/* This function is called whenever a process tries to  * do an ioctl on our device file. We get two extra  * parameters (additional to the inode and file  * structures, which all device functions get): the number * of the ioctl called and the parameter given to the  * ioctl function. * * If the ioctl is write or read/write (meaning output  * is returned to the calling process), the ioctl call  * returns the output of this function. *//*int device_ioctl(    struct inode *inode,    struct file *file,    unsigned int ioctl_num,// The number of the ioctl     unsigned long ioctl_param) // The parameter to it {}*//*****************************File operations define************************/struct file_operations Fops = {    .open = device_open,    //open    .release = device_release,    //release	.read = device_read,	.write = device_write};/****************************Module initialize******************************/static int __init mcpcan_init_module(void){        int res;        //EXPORT_NO_SYMBOLS;//       printk(KERN_ERR "hello,enter mcpcan_init_module!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");        /* Register the character device (atleast try) */        res = register_chrdev(MCP_major,"MCPCAN",&Fops);        if(res < 0) {               printk("device register failed with %d.\n",res);               return res;        }        if(MCP_major == 0) MCP_major = res;	    MCP_device_init();       //intmsk = ioremap(0x4A000008,4);    eintmask = ioremap(0x560000A4,4);   // extint0 = ioremap(0x56000088,4);    //extint1 = ioremap(0x5600008c,4);    //extint2 = ioremap(0x56000090,4);        //map spi regs for spi.c    spcon0 = ioremap(0x59000000,4);    spsta0 = ioremap(0x59000004,4);    sppin0 = ioremap(0x59000008,4);    sppre0 = ioremap(0x5900000c,4);    sptdat0 = ioremap(0x59000010,4);    sprdat0 = ioremap(0x59000014,4);        spcon1 = ioremap(0x59000020,4);    spsta1 = ioremap(0x59000024,4);    sppin1 = ioremap(0x59000028,4);    sppre1 = ioremap(0x5900002c,4);    sptdat1 = ioremap(0x59000030,4);    sprdat1 = ioremap(0x59000034,4);        //printk(KERN_ERR "in mcpcan.c:the maped addr of sptdat = %#p",sptdat0);		//printk ("%s The major device number is %d.\n",			//	"Registeration is a success", 			//	MCP_major);		          		printk (KERN_ERR "hello,you have insert module that support MCP2510,to make\n");		printk (KERN_ERR "use of it, you must use: mknod /dev/%s c %d 0,and you can\n","can",MCP_major);		printk (KERN_ERR "run test demo named 2510test for a test in loop back mode\n");    printk (KERN_ERR "you'll modify the driver to make it fall into normal mode\n");        return 0;}/****************************Module release********************************/static void __exit mcpcan_cleanup_module(void){	int i;    unregister_chrdev(MCP_major,"MCPCAN");	for(i=0; i<2; i++){		kfree((void *)Device[i]->RecvBuf);		kfree(Device[i]->SendBuf);		kfree(Device[i]);	}    printk("MCPCAN release success.\n");}module_init(mcpcan_init_module);module_exit(mcpcan_cleanup_module);MODULE_AUTHOR("witech <bdht@witech.com.cn>");MODULE_DESCRIPTION("MCP251X driver");MODULE_LICENSE("Dual BSD/GPL");

⌨️ 快捷键说明

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