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

📄 nvram.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * CMOS/NV-RAM driver for Linux * * Copyright (C) 1997 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> * idea by and with help from Richard Jelinek <rj@suse.de> * * This driver allows you to access the contents of the non-volatile memory in * the mc146818rtc.h real-time clock. This chip is built into all PCs and into * many Atari machines. In the former it's called "CMOS-RAM", in the latter * "NVRAM" (NV stands for non-volatile). * * The data are supplied as a (seekable) character device, /dev/nvram. The * size of this file is 50, the number of freely available bytes in the memory * (i.e., not used by the RTC itself). *  * Checksums over the NVRAM contents are managed by this driver. In case of a * bad checksum, reads and writes return -EIO. The checksum can be initialized * to a sane state either by ioctl(NVRAM_INIT) (clear whole NVRAM) or * ioctl(NVRAM_SETCKS) (doesn't change contents, just makes checksum valid * again; use with care!) * * This file also provides some functions for other parts of the kernel that * want to access the NVRAM: nvram_{read,write,check_checksum,set_checksum}. * Obviously this can be used only if this driver is always configured into * the kernel and is not a module. Since the functions are used by some Atari * drivers, this is the case on the Atari. * * * 	1.1	Cesar Barros: SMP locking fixes * 		added changelog */#define NVRAM_VERSION		"1.1"#include <linux/module.h>#include <linux/config.h>#include <linux/sched.h>#include <linux/smp_lock.h>#define PC		1#define ATARI	2/* select machine configuration */#if defined(CONFIG_ATARI)#define MACH ATARI#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */#define MACH PC#else#error Cannot build nvram driver for this machine configuration.#endif#if MACH == PC/* RTC in a PC */#define CHECK_DRIVER_INIT() 1/* On PCs, the checksum is built only over bytes 2..31 */#define PC_CKS_RANGE_START	2#define PC_CKS_RANGE_END	31#define PC_CKS_LOC			32#define	mach_check_checksum	pc_check_checksum#define	mach_set_checksum	pc_set_checksum#define	mach_proc_infos		pc_proc_infos#endif#if MACH == ATARI/* Special parameters for RTC in Atari machines */#include <asm/atarihw.h>#include <asm/atariints.h>#define RTC_PORT(x)			(TT_RTC_BAS + 2*(x))#define CHECK_DRIVER_INIT() (MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK))/* On Ataris, the checksum is over all bytes except the checksum bytes * themselves; these are at the very end */#define ATARI_CKS_RANGE_START	0#define ATARI_CKS_RANGE_END		47#define ATARI_CKS_LOC			48#define	mach_check_checksum	atari_check_checksum#define	mach_set_checksum	atari_set_checksum#define	mach_proc_infos		atari_proc_infos#endif/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with * rtc_lock held. Due to the index-port/data-port design of the RTC, we * don't want two different things trying to get to it at once. (e.g. the * periodic 11 min sync from time.c vs. this driver.) */#include <linux/types.h>#include <linux/errno.h>#include <linux/miscdevice.h>#include <linux/slab.h>#include <linux/ioport.h>#include <linux/fcntl.h>#include <linux/mc146818rtc.h>#include <linux/nvram.h>#include <linux/init.h>#include <linux/proc_fs.h>#include <linux/spinlock.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/system.h>static int nvram_open_cnt;	/* #times opened */static int nvram_open_mode;		/* special open modes */#define	NVRAM_WRITE		1		/* opened for writing (exclusive) */#define	NVRAM_EXCL		2		/* opened with O_EXCL */#define	RTC_FIRST_BYTE		14	/* RTC register number of first NVRAM byte */#define	NVRAM_BYTES			128-RTC_FIRST_BYTE	/* number of NVRAM bytes */static int mach_check_checksum( void );static void mach_set_checksum( void );#ifdef CONFIG_PROC_FSstatic int mach_proc_infos( unsigned char *contents, char *buffer, int *len,							off_t *begin, off_t offset, int size );#endif/* * These are the internal NVRAM access functions, which do NOT disable * interrupts and do not check the checksum. Both tasks are left to higher * level function, so they need to be done only once per syscall. */static __inline__ unsigned char nvram_read_int( int i ){	return( CMOS_READ( RTC_FIRST_BYTE+i ) );}static __inline__ void nvram_write_int( unsigned char c, int i ){	CMOS_WRITE( c, RTC_FIRST_BYTE+i );}static __inline__ int nvram_check_checksum_int( void ){	return( mach_check_checksum() );}static __inline__ void nvram_set_checksum_int( void ){	mach_set_checksum();}#if MACH == ATARI/* * These non-internal functions are provided to be called by other parts of * the kernel. It's up to the caller to ensure correct checksum before reading * or after writing (needs to be done only once). * * They're only built if CONFIG_ATARI is defined, because Atari drivers use * them. For other configurations (PC), the rest of the kernel can't rely on * them being present (this driver may not be configured at all, or as a * module), so they access config information themselves. */unsigned char nvram_read_byte( int i ){	unsigned long flags;	unsigned char c;	spin_lock_irqsave (&rtc_lock, flags);	c = nvram_read_int( i );	spin_unlock_irqrestore (&rtc_lock, flags);	return( c );}/* This races nicely with trying to read with checksum checking (nvram_read) */void nvram_write_byte( unsigned char c, int i ){	unsigned long flags;	spin_lock_irqsave (&rtc_lock, flags);	nvram_write_int( c, i );	spin_unlock_irqrestore (&rtc_lock, flags);}int nvram_check_checksum( void ){	unsigned long flags;	int rv;	spin_lock_irqsave (&rtc_lock, flags);	rv = nvram_check_checksum_int();	spin_unlock_irqrestore (&rtc_lock, flags);	return( rv );}void nvram_set_checksum( void ){	unsigned long flags;	spin_lock_irqsave (&rtc_lock, flags);	nvram_set_checksum_int();	spin_unlock_irqrestore (&rtc_lock, flags);}#endif /* MACH == ATARI *//* * The are the file operation function for user access to /dev/nvram */static long long nvram_llseek(struct file *file,loff_t offset, int origin ){	switch( origin ) {	  case 0:		/* nothing to do */		break;	  case 1:		offset += file->f_pos;		break;	  case 2:		offset += NVRAM_BYTES;		break;	}	return( (offset >= 0) ? (file->f_pos = offset) : -EINVAL );}static ssize_t nvram_read(struct file * file,	char * buf, size_t count, loff_t *ppos ){	char contents [NVRAM_BYTES];	unsigned i = *ppos;	char *tmp;	spin_lock_irq (&rtc_lock);		if (!nvram_check_checksum_int())		goto checksum_err;	for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)		*tmp = nvram_read_int(i);	spin_unlock_irq (&rtc_lock);	if (copy_to_user (buf, contents, tmp - contents))		return -EFAULT;	*ppos = i;	return (tmp - contents);checksum_err:	spin_unlock_irq (&rtc_lock);	return -EIO;}static ssize_t nvram_write(struct file * file,		const char * buf, size_t count, loff_t *ppos ){	char contents [NVRAM_BYTES];	unsigned i = *ppos;	char * tmp;	if (copy_from_user (contents, buf, (NVRAM_BYTES - i) < count ?						(NVRAM_BYTES - i) : count))		return -EFAULT;	spin_lock_irq (&rtc_lock);	if (!nvram_check_checksum_int())		goto checksum_err;	for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)		nvram_write_int (*tmp, i);	nvram_set_checksum_int();	spin_unlock_irq (&rtc_lock);	*ppos = i;	return (tmp - contents);checksum_err:	spin_unlock_irq (&rtc_lock);	return -EIO;}static int nvram_ioctl( struct inode *inode, struct file *file,						unsigned int cmd, unsigned long arg ){	int i;		switch( cmd ) {	  case NVRAM_INIT:			/* initialize NVRAM contents and checksum */		if (!capable(CAP_SYS_ADMIN))			return( -EACCES );		spin_lock_irq (&rtc_lock);		for( i = 0; i < NVRAM_BYTES; ++i )			nvram_write_int( 0, i );		nvram_set_checksum_int();				spin_unlock_irq (&rtc_lock);		return( 0 );	  	  case NVRAM_SETCKS:		/* just set checksum, contents unchanged								 * (maybe useful after checksum garbaged								 * somehow...) */		if (!capable(CAP_SYS_ADMIN))			return( -EACCES );		spin_lock_irq (&rtc_lock);		nvram_set_checksum_int();		spin_unlock_irq (&rtc_lock);		return( 0 );	  default:		return( -EINVAL );	}}static int nvram_open( struct inode *inode, struct file *file ){	if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||		(nvram_open_mode & NVRAM_EXCL) ||		((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE)))		return( -EBUSY );	if (file->f_flags & O_EXCL)		nvram_open_mode |= NVRAM_EXCL;	if (file->f_mode & 2)		nvram_open_mode |= NVRAM_WRITE;	nvram_open_cnt++;	return( 0 );}static int nvram_release( struct inode *inode, struct file *file ){	lock_kernel();	nvram_open_cnt--;	if (file->f_flags & O_EXCL)		nvram_open_mode &= ~NVRAM_EXCL;	if (file->f_mode & 2)		nvram_open_mode &= ~NVRAM_WRITE;	unlock_kernel();	return( 0 );}

⌨️ 快捷键说明

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