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

📄 eepromdriver.c

📁 eeprom驱动
💻 C
字号:
#ifndef __KERNEL__#define __KERNEL__#endif#ifndef MODULE#define MODULE#endif#include <linux/config.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/module.h>#include <asm/irq.h>   //disable && enable irq#include <asm/uaccess.h>//copy_from_user | to_user#include <linux/ioctl.h>#include <linux/fs.h>       /* everything... */#include <asm/io.h>#include <linux/ioport.h>//ioremap#include <linux/sched.h>//wait_queue#include <linux/wait.h>#include <linux/mm.h>#include <linux/slab.h> //kmalloc#include <linux/interrupt.h>#include <linux/cdev.h>#include <linux/delay.h>#include <linux/time.h>#define DRIVER_VERSION "v1.0"MODULE_LICENSE("Dual BSD/GPL");#define INT8U	unsigned char#define INT32U	unsigned int#define INT32	signed int#define SMBUS_BASE       0x56fffff0volatile unsigned char *smbase_addr = NULL;#define SMBus_CLH		(*((volatile INT8U *) smbase_addr+1))#define SMBus_CLL		(*((volatile INT8U *) smbase_addr))#define SMBus_CON		(*((volatile INT8U *) smbase_addr+2))#define SMBus_CMD		(*((volatile INT8U *) smbase_addr+4))#define SMBus_TXR		(*((volatile INT8U *) smbase_addr+3))#define SMBus_RXR		(*((volatile INT8U *) smbase_addr+3))#define SMBus_STS		(*((volatile INT8U *) smbase_addr+4))#define READ			0#define WRITE			1int eeprom_major = -1;struct eeprom_addr_string{	INT32U addr;	INT32U num;					//每一条目包含的字符数	char string[20];            //eeprom芯片AT24C02,256Byte。前16Byte用于存放mac								//后240byte用于存放固件的ascii码								//固件版本每16byte作为一个条目,最多支持15个条目								//每个条目最大16个字符};void SMBus_Init(INT8U CLH,INT8U CLL);INT8U SMBus_SendStr(INT8U sla, INT8U suba, INT8U *s, INT8U no);INT8U SMBus_RecvStr(INT8U sla, INT8U suba, INT8U *s, INT8U no);void SMBus_Init(INT8U CLH,INT8U CLL){	SMBus_CLH = CLH;	SMBus_CLL = CLL;	SMBus_CON = 0xc0;				// Enable SMBus and Interrupt Output}static int eeprom_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long argv){	struct eeprom_addr_string ras,was;	memset (&ras,0,sizeof(struct eeprom_addr_string));	memset (&was,0,sizeof(struct eeprom_addr_string));	switch ( cmd )			//每次调用读写一个条目,最大16Byte	{		case WRITE:			copy_from_user(&was,(void *)argv,sizeof(struct eeprom_addr_string));			printk("WRITE:addr:%x,num:%x,string:%s\n",was.addr,was.num,was.string);			if ( was.num <= 8 )				SMBus_SendStr(0xa0, was.addr, was.string, was.num);			else if ( 8 < was.num && was.num <= 16 )			{//				printk("KERN:was.num:%d\n",was.num);				SMBus_SendStr(0xa0, was.addr, &was.string[0], 8);				mdelay(100);				SMBus_SendStr(0xa0, was.addr+8, &was.string[8], was.num-8);			}			else			{				printk("Error:was.num=%d\n",was.num);				return -1;			}			break;		case READ:			copy_from_user(&ras,(void *)argv,sizeof(struct eeprom_addr_string));			printk("READ:addr:%x,num:%x,string:%s\n",ras.addr,ras.num,ras.string);			if ( ras.num <= 8 )				SMBus_RecvStr(0xa0, ras.addr, ras.string, ras.num);			else if ( 8 < ras.num && ras.num <= 16 )			{//				printk("KERN:ras.num:%d\n",ras.num);				SMBus_RecvStr(0xa0, ras.addr, &ras.string[0], 8);				mdelay(100);				SMBus_RecvStr(0xa0, ras.addr+8, &ras.string[8], ras.num-8);			}			else			{				printk("Error:ras.num=%d\n",ras.num);				return -1;			}//			printk("KERN:string:%s\n",ras.string);			copy_to_user((void *)argv,&ras,sizeof(struct eeprom_addr_string));			break;		default:			printk("cmd error\n");			return -1;	}	return 0;}INT8U SMBus_SendStr(INT8U sla, INT8U suba, INT8U *s, INT8U no){    INT8U sla_ack, i;    SMBus_TXR = sla;    SMBus_CMD = 0x90;    while ((SMBus_STS & 0x01) != 0x01);    SMBus_CMD = 0x01;    sla_ack = SMBus_STS & 0x80;    if (sla_ack != 0x00)    {        return 0;    }    SMBus_TXR = suba;    SMBus_CMD = 0x10;    while ((SMBus_STS & 0x01) != 0x01);    SMBus_CMD = 0x01;    sla_ack = SMBus_STS & 0x80;    if (sla_ack != 0x00)    {        return 0;    }    for (i = 0; i < no - 1; i++)    {        SMBus_TXR = *s;        SMBus_CMD = 0x10;        while ((SMBus_STS & 0x01) != 0x01);        SMBus_CMD = 0x01;        sla_ack = SMBus_STS & 0x80;        if (sla_ack != 0x00)        {            return 0;        }        s++;    }    SMBus_TXR = *s;    SMBus_CMD = 0x50;    while ((SMBus_STS & 0x01) != 0x01);    SMBus_CMD = 0x01;    sla_ack = SMBus_STS & 0x80;    if (sla_ack != 0x00)    {        return 0;    }    return 1;}INT8U SMBus_RecvStr(INT8U sla, INT8U suba, INT8U *s, INT8U no){    INT8U sla_ack, i;    SMBus_TXR = sla;    SMBus_CMD = 0x90;    while ((SMBus_STS & 0x01) != 0x01);    SMBus_CMD = 0x01;    sla_ack = SMBus_STS & 0x80;    if (sla_ack != 0x00)    {        return 0;    }    SMBus_TXR = suba;    SMBus_CMD = 0x10;    while ((SMBus_STS & 0x01) != 0x01);    SMBus_CMD = 0x01;    sla_ack = SMBus_STS & 0x80;    if (sla_ack != 0x00)    {        return 0;    }    SMBus_TXR = sla + 1;    SMBus_CMD = 0x90;    while ((SMBus_STS & 0x01) != 0x01);    SMBus_CMD = 0x01;    sla_ack = SMBus_STS & 0x80;    if (sla_ack != 0x00)    {        return 0;    }    for (i = 0; i < no - 1; i++)    {        SMBus_CMD = 0x20;        while ((SMBus_STS & 0x01) != 0x01);        SMBus_CMD = 0x01;        if (sla_ack != 0x00)        {            return 0;        }        *s = SMBus_RXR;        s++;    }    SMBus_CMD = 0x68;    while ((SMBus_STS & 0x01) != 0x01);    SMBus_CMD = 0x01;    *s = SMBus_RXR;    return(1);}struct file_operations eeprom_fops = {	.owner =    THIS_MODULE,	.ioctl =    eeprom_ioctl,};static int __init eeprom_init(void){	smbase_addr=(volatile unsigned char *)ioremap_nocache(SMBUS_BASE,5);	eeprom_major = register_chrdev(231, "eeprom", &eeprom_fops);	printk("eeprom_major:%d\n",eeprom_major);	SMBus_Init(0x01, 0x00);	printk("Hello EEPROM!\n");	return 0;}static void __exit eeprom_exit(void){	unregister_chrdev(eeprom_major, "eeprom");	iounmap((void *)smbase_addr);	printk("Bye EEPROM.\n");}module_init(eeprom_init);module_exit(eeprom_exit);

⌨️ 快捷键说明

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