diff options
4 files changed, 153 insertions, 982 deletions
diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/Makefile b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/Makefile index f2096137e..e08cf9acb 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/Makefile +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/Makefile @@ -9,7 +9,7 @@ O_TARGET        := bcm947xx.o  export-objs     := export.o  obj-y		:= prom.o setup.o time.o sbmips.o gpio.o -obj-y		+= nvram.o nvram_linux.o cfe_env.o hndpmu.o +obj-y		+= nvram.o cfe_env.o hndpmu.o  obj-y		+= sbutils.o utils.o bcmsrom.o hndchipc.o  obj-$(CONFIG_PCI) += sbpci.o pcibios.o  obj-y 		+= export.o diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/export.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/export.c index ff3e03197..35a578aa6 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/export.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/export.c @@ -69,9 +69,6 @@ _export(getintvar)  _export(nvram_get)  _export(nvram_getall) -_export(nvram_set) -_export(nvram_unset) -_export(nvram_commit)  _export(srom_read)  _export(srom_write) diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c index c37023bce..e93752a37 100644 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c +++ b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram.c @@ -1,7 +1,7 @@  /* - * NVRAM variable manipulation (common) + * NVRAM variable manipulation (Linux kernel half)   * - * Copyright 2004, Broadcom Corporation + * Copyright 2006, Broadcom Corporation   * All Rights Reserved.   *    * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -11,306 +11,203 @@   *   */ +#include <linux/config.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/bootmem.h> +#include <linux/wrapper.h> +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <linux/mtd/mtd.h> +#include <asm/addrspace.h> +#include <asm/io.h> +#include <asm/uaccess.h> +  #include <typedefs.h>  #include <osl.h>  #include <bcmendian.h>  #include <bcmnvram.h> -#include <sbsdram.h> - -extern struct nvram_tuple * BCMINIT(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value); -extern void BCMINIT(_nvram_free)(struct nvram_tuple *t); -extern int BCMINIT(_nvram_read)(void *buf); - -char * BCMINIT(_nvram_get)(const char *name); -int BCMINIT(_nvram_set)(const char *name, const char *value); -int BCMINIT(_nvram_unset)(const char *name); -int BCMINIT(_nvram_getall)(char *buf, int count); -int BCMINIT(_nvram_commit)(struct nvram_header *header); -int BCMINIT(_nvram_init)(void); -void BCMINIT(_nvram_exit)(void); - -static struct nvram_tuple * BCMINITDATA(nvram_hash)[257]; -static struct nvram_tuple * nvram_dead; - -/* Free all tuples. Should be locked. */ -static void   -BCMINITFN(nvram_free)(void) -{ -	uint i; -	struct nvram_tuple *t, *next; - -	/* Free hash table */ -	for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { -		for (t = BCMINIT(nvram_hash)[i]; t; t = next) { -			next = t->next; -			BCMINIT(_nvram_free)(t); -		} -		BCMINIT(nvram_hash)[i] = NULL; -	} +#include <sbconfig.h> +#include <sbchipc.h> +#include <sbutils.h> +#include <hndmips.h> +#include <sflash.h> -	/* Free dead table */ -	for (t = nvram_dead; t; t = next) { -		next = t->next; -		BCMINIT(_nvram_free)(t); -	} -	nvram_dead = NULL; +/* In BSS to minimize text size and page aligned so it can be mmap()-ed */ +static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE))); -	/* Indicate to per-port code that all tuples have been freed */ -	BCMINIT(_nvram_free)(NULL); -} +/* Global SB handle */ +extern void *bcm947xx_sbh; +extern spinlock_t bcm947xx_sbh_lock; -/* String hash */ -static INLINE uint -hash(const char *s) -{ -	uint hash = 0; - -	while (*s) -		hash = 31 * hash + *s++; +static int cfe_env; +extern char *cfe_env_get(char *nv_buf, const char *name); -	return hash; -} +/* Convenience */ +#define sbh bcm947xx_sbh +#define sbh_lock bcm947xx_sbh_lock -/* (Re)initialize the hash table. Should be locked. */ -static int  -BCMINITFN(nvram_rehash)(struct nvram_header *header) +/* Probe for NVRAM header */ +static void __init +early_nvram_init(void)  { -	char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq; - -	/* (Re)initialize hash table */ -	BCMINIT(nvram_free)(); +	struct nvram_header *header; +	chipcregs_t *cc; +	struct sflash *info = NULL; +	int i; +	uint32 base, off, lim; +	u32 *src, *dst; + +	if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) { +		base = KSEG1ADDR(SB_FLASH2); +		switch (readl(&cc->capabilities) & CC_CAP_FLASH_MASK) { +		case PFLASH: +			lim = SB_FLASH2_SZ; +			break; -	/* Parse and set "name=value\0 ... \0\0" */ -	name = (char *) &header[1]; -	end = (char *) header + NVRAM_SPACE - 2; -	end[0] = end[1] = '\0'; -	for (; *name; name = value + strlen(value) + 1) { -		if (!(eq = strchr(name, '='))) +		case SFLASH_ST: +		case SFLASH_AT: +			if ((info = sflash_init(sbh,cc)) == NULL) +				return; +			lim = info->size;  			break; -		*eq = '\0'; -		value = eq + 1; -		BCMINIT(_nvram_set)(name, value); -		*eq = '='; -	} -	/* Set special SDRAM parameters */ -	if (!BCMINIT(_nvram_get)("sdram_init")) { -		sprintf(buf, "0x%04X", (uint16)(header->crc_ver_init >> 16)); -		BCMINIT(_nvram_set)("sdram_init", buf); -	} -	if (!BCMINIT(_nvram_get)("sdram_config")) { -		sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff)); -		BCMINIT(_nvram_set)("sdram_config", buf); -	} -	if (!BCMINIT(_nvram_get)("sdram_refresh")) { -		sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff)); -		BCMINIT(_nvram_set)("sdram_refresh", buf); -	} -	if (!BCMINIT(_nvram_get)("sdram_ncdl")) { -		sprintf(buf, "0x%08X", header->config_ncdl); -		BCMINIT(_nvram_set)("sdram_ncdl", buf); +		case FLASH_NONE: +		default: +			return; +		} +	} else { +		/* extif assumed, Stop at 4 MB */ +		base = KSEG1ADDR(SB_FLASH1); +		lim = SB_FLASH1_SZ;  	} -	return 0; -} - -/* Get the value of an NVRAM variable. Should be locked. */ -char *  -BCMINITFN(_nvram_get)(const char *name) -{ -	uint i; -	struct nvram_tuple *t; -	char *value; - -	if (!name) -		return NULL; - -	/* Hash the name */ -	i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); - -	/* Find the associated tuple in the hash table */ -	for (t = BCMINIT(nvram_hash)[i]; t && strcmp(t->name, name); t = t->next); - -	value = t ? t->value : NULL; +	/* XXX: hack for supporting the CFE environment stuff on WGT634U */ +	src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000); +	dst = (u32 *) nvram_buf; +	if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) { +		printk("early_nvram_init: WGT634U NVRAM found.\n"); -	return value; -} - -/* Get the value of an NVRAM variable. Should be locked. */ -int  -BCMINITFN(_nvram_set)(const char *name, const char *value) -{ -	uint i; -	struct nvram_tuple *t, *u, **prev; - -	/* Hash the name */ -	i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); - -	/* Find the associated tuple in the hash table */ -	for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev); - -	/* (Re)allocate tuple */ -	if (!(u = BCMINIT(_nvram_realloc)(t, name, value))) -		return -12; /* -ENOMEM */ - -	/* Value reallocated */ -	if (t && t == u) -		return 0; - -	/* Move old tuple to the dead table */ -	if (t) { -		*prev = t->next; -		t->next = nvram_dead; -		nvram_dead = t; +		for (i = 0; i < 0x1ff0; i++) { +			if (*src == 0xFFFFFFFF) +				break; +			*dst++ = *src++; +		} +		cfe_env = 1; +		return;  	} -	/* Add new tuple to the hash table */ -	u->next = BCMINIT(nvram_hash)[i]; -	BCMINIT(nvram_hash)[i] = u; +	off = FLASH_MIN; +	while (off <= lim) { +		/* Windowed flash access */ +		header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); +		if (header->magic == NVRAM_MAGIC) +			goto found; +		off <<= 1; +	} -	return 0; +	/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ +	header = (struct nvram_header *) KSEG1ADDR(base + 4 * 1024); +	if (header->magic == NVRAM_MAGIC) +		goto found; +	 +	header = (struct nvram_header *) KSEG1ADDR(base + 1 * 1024); +	if (header->magic == NVRAM_MAGIC) +		goto found; +	 +	printk("early_nvram_init: NVRAM not found\n"); +	return; + +found: +	src = (u32 *) header; +	dst = (u32 *) nvram_buf; +	for (i = 0; i < sizeof(struct nvram_header); i += 4) +		*dst++ = *src++; +	for (; i < header->len && i < NVRAM_SPACE; i += 4) +		*dst++ = ltoh32(*src++);  } -/* Unset the value of an NVRAM variable. Should be locked. */ -int  -BCMINITFN(_nvram_unset)(const char *name) +/* Early (before mm or mtd) read-only access to NVRAM */ +static char * __init +early_nvram_get(const char *name)  { -	uint i; -	struct nvram_tuple *t, **prev; +	char *var, *value, *end, *eq;  	if (!name) -		return 0; +		return NULL; + +	/* Too early? */ +	if (sbh == NULL) +		return NULL; -	/* Hash the name */ -	i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash)); +	if (!nvram_buf[0]) +		early_nvram_init(); -	/* Find the associated tuple in the hash table */ -	for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev); +	if (cfe_env) +		return cfe_env_get(nvram_buf, name); -	/* Move it to the dead table */ -	if (t) { -		*prev = t->next; -		t->next = nvram_dead; -		nvram_dead = t; +	/* Look for name=value and return value */ +	var = &nvram_buf[sizeof(struct nvram_header)]; +	end = nvram_buf + sizeof(nvram_buf) - 2; +	end[0] = end[1] = '\0'; +	for (; *var; var = value + strlen(value) + 1) { +		if (!(eq = strchr(var, '='))) +			break; +		value = eq + 1; +		if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0) +			return value;  	} -	return 0; +	return NULL;  } -/* Get all NVRAM variables. Should be locked. */ -int  -BCMINITFN(_nvram_getall)(char *buf, int count) +static int __init +early_nvram_getall(char *buf, int count)  { -	uint i; -	struct nvram_tuple *t; +	char *var, *end;  	int len = 0; +	 +	/* Too early? */ +	if (sbh == NULL) +		return -1; + +	if (!nvram_buf[0]) +		early_nvram_init();  	bzero(buf, count);  	/* Write name=value\0 ... \0\0 */ -	for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { -		for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) { -			if ((count - len) > (strlen(t->name) + 1 + strlen(t->value) + 1)) -				len += sprintf(buf + len, "%s=%s", t->name, t->value) + 1; -			else -				break; -		} +	var = &nvram_buf[sizeof(struct nvram_header)]; +	end = nvram_buf + sizeof(nvram_buf) - 2; +	end[0] = end[1] = '\0'; +	for (; *var; var += strlen(var) + 1) { +		if ((count - len) <= (strlen(var) + 1)) +			break; +		len += sprintf(buf + len, "%s", var) + 1;  	}  	return 0;  } -/* Regenerate NVRAM. Should be locked. */ -int -BCMINITFN(_nvram_commit)(struct nvram_header *header) -{ -	char *init, *config, *refresh, *ncdl; -	char *ptr, *end; -	int i; -	struct nvram_tuple *t; -	struct nvram_header tmp; -	uint8 crc; - -	/* Regenerate header */ -	header->magic = NVRAM_MAGIC; -	header->crc_ver_init = (NVRAM_VERSION << 8); -	if (!(init = BCMINIT(_nvram_get)("sdram_init")) || -	    !(config = BCMINIT(_nvram_get)("sdram_config")) || -	    !(refresh = BCMINIT(_nvram_get)("sdram_refresh")) || -	    !(ncdl = BCMINIT(_nvram_get)("sdram_ncdl"))) { -		header->crc_ver_init |= SDRAM_INIT << 16; -		header->config_refresh = SDRAM_CONFIG; -		header->config_refresh |= SDRAM_REFRESH << 16; -		header->config_ncdl = 0; -	} else { -		header->crc_ver_init |= (simple_strtoul(init, NULL, 0) & 0xffff) << 16; -		header->config_refresh = simple_strtoul(config, NULL, 0) & 0xffff; -		header->config_refresh |= (simple_strtoul(refresh, NULL, 0) & 0xffff) << 16; -		header->config_ncdl = simple_strtoul(ncdl, NULL, 0); -	} - -	/* Clear data area */ -	ptr = (char *) header + sizeof(struct nvram_header); -	bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header)); -	/* Leave space for a double NUL at the end */ -	end = (char *) header + NVRAM_SPACE - 2; - -	/* Write out all tuples */ -	for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) { -		for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) { -			if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end) -				break; -			ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1; -		} -	} - -	/* End with a double NUL */ -	ptr += 2; - -	/* Set new length */ -	header->len = ROUNDUP(ptr - (char *) header, 4); - -	/* Little-endian CRC8 over the last 11 bytes of the header */ -	tmp.crc_ver_init = htol32(header->crc_ver_init); -	tmp.config_refresh = htol32(header->config_refresh); -	tmp.config_ncdl = htol32(header->config_ncdl); -	crc = hndcrc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, 0xff); - -	/* Continue CRC8 over data bytes */ -	crc = hndcrc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc); - -	/* Set new CRC8 */ -	header->crc_ver_init |= crc; - -	/* Reinitialize hash table */ -	return BCMINIT(nvram_rehash)(header); +char * +nvram_get(const char *name) +{ +	return early_nvram_get(name);  } -/* Initialize hash table. Should be locked. */ -int  -BCMINITFN(_nvram_init)(void) +int +nvram_getall(char *buf, int count)  { -	struct nvram_header *header; +	unsigned long flags;  	int ret; -	if (!(header = (struct nvram_header *) kmalloc(NVRAM_SPACE, GFP_ATOMIC))) { -		return -12; /* -ENOMEM */ -	} - -	if ((ret = BCMINIT(_nvram_read)(header)) == 0 && -	    header->magic == NVRAM_MAGIC) -		BCMINIT(nvram_rehash)(header); - -	kfree(header); -	return ret; -} - -/* Free hash table. Should be locked. */ -void  -BCMINITFN(_nvram_exit)(void) -{ -	BCMINIT(nvram_free)(); +	return early_nvram_getall(buf, count);  }  /* @@ -331,8 +228,7 @@ getvar(char *vars, const char *name)  		if ((memcmp(s, name, len) == 0) && (s[len] == '='))  			return (&s[len+1]); -		while (*s++) -			; +		while (*s++);  	}  	/* then query nvram */ @@ -354,4 +250,3 @@ getintvar(char *vars, const char *name)  	return (simple_strtoul(val, NULL, 0));  } - diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram_linux.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram_linux.c deleted file mode 100644 index b04815d90..000000000 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/nvram_linux.c +++ /dev/null @@ -1,721 +0,0 @@ -/* - * NVRAM variable manipulation (Linux kernel half) - * - * Copyright 2006, Broadcom Corporation - * All Rights Reserved. - *  - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - * - */ - -#include <linux/config.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/bootmem.h> -#include <linux/wrapper.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/mtd/mtd.h> -#include <asm/addrspace.h> -#include <asm/io.h> -#include <asm/uaccess.h> - -#include <typedefs.h> -#include <osl.h> -#include <bcmendian.h> -#include <bcmnvram.h> -#include <sbconfig.h> -#include <sbchipc.h> -#include <sbutils.h> -#include <hndmips.h> -#include <sflash.h> - -/* In BSS to minimize text size and page aligned so it can be mmap()-ed */ -static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE))); - -#ifdef MODULE - -#define early_nvram_get(name) nvram_get(name) - -#else /* !MODULE */ - -/* Global SB handle */ -extern void *bcm947xx_sbh; -extern spinlock_t bcm947xx_sbh_lock; - -static int cfe_env; -extern char *cfe_env_get(char *nv_buf, const char *name); - -/* Convenience */ -#define sbh bcm947xx_sbh -#define sbh_lock bcm947xx_sbh_lock -#define KB * 1024 -#define MB * 1024 * 1024 - -/* Probe for NVRAM header */ -static void __init -early_nvram_init(void) -{ -	struct nvram_header *header; -	chipcregs_t *cc; -	struct sflash *info = NULL; -	int i; -	uint32 base, off, lim; -	u32 *src, *dst; - -	if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) { -		base = KSEG1ADDR(SB_FLASH2); -		switch (readl(&cc->capabilities) & CC_CAP_FLASH_MASK) { -		case PFLASH: -			lim = SB_FLASH2_SZ; -			break; - -		case SFLASH_ST: -		case SFLASH_AT: -			if ((info = sflash_init(sbh,cc)) == NULL) -				return; -			lim = info->size; -			break; - -		case FLASH_NONE: -		default: -			return; -		} -	} else { -		/* extif assumed, Stop at 4 MB */ -		base = KSEG1ADDR(SB_FLASH1); -		lim = SB_FLASH1_SZ; -	} - -	/* XXX: hack for supporting the CFE environment stuff on WGT634U */ -	src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000); -	dst = (u32 *) nvram_buf; -	if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) { -		printk("early_nvram_init: WGT634U NVRAM found.\n"); - -		for (i = 0; i < 0x1ff0; i++) { -			if (*src == 0xFFFFFFFF) -				break; -			*dst++ = *src++; -		} -		cfe_env = 1; -		return; -	} - -	off = FLASH_MIN; -	while (off <= lim) { -		/* Windowed flash access */ -		header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); -		if (header->magic == NVRAM_MAGIC) -			goto found; -		off <<= 1; -	} - -	/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ -	header = (struct nvram_header *) KSEG1ADDR(base + 4 KB); -	if (header->magic == NVRAM_MAGIC) -		goto found; -	 -	header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); -	if (header->magic == NVRAM_MAGIC) -		goto found; -	 -	printk("early_nvram_init: NVRAM not found\n"); -	return; - -found: -	src = (u32 *) header; -	dst = (u32 *) nvram_buf; -	for (i = 0; i < sizeof(struct nvram_header); i += 4) -		*dst++ = *src++; -	for (; i < header->len && i < NVRAM_SPACE; i += 4) -		*dst++ = ltoh32(*src++); -} - -/* Early (before mm or mtd) read-only access to NVRAM */ -static char * __init -early_nvram_get(const char *name) -{ -	char *var, *value, *end, *eq; - -	if (!name) -		return NULL; - -	/* Too early? */ -	if (sbh == NULL) -		return NULL; - -	if (!nvram_buf[0]) -		early_nvram_init(); - -	if (cfe_env) -		return cfe_env_get(nvram_buf, name); - -	/* Look for name=value and return value */ -	var = &nvram_buf[sizeof(struct nvram_header)]; -	end = nvram_buf + sizeof(nvram_buf) - 2; -	end[0] = end[1] = '\0'; -	for (; *var; var = value + strlen(value) + 1) { -		if (!(eq = strchr(var, '='))) -			break; -		value = eq + 1; -		if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0) -			return value; -	} - -	return NULL; -} - -static int __init -early_nvram_getall(char *buf, int count) -{ -	char *var, *end; -	int len = 0; -	 -	/* Too early? */ -	if (sbh == NULL) -		return -1; - -	if (!nvram_buf[0]) -		early_nvram_init(); - -	bzero(buf, count); - -	/* Write name=value\0 ... \0\0 */ -	var = &nvram_buf[sizeof(struct nvram_header)]; -	end = nvram_buf + sizeof(nvram_buf) - 2; -	end[0] = end[1] = '\0'; -	for (; *var; var += strlen(var) + 1) { -		if ((count - len) <= (strlen(var) + 1)) -			break; -		len += sprintf(buf + len, "%s", var) + 1; -	} - -	return 0; -} -#endif /* !MODULE */ - -extern char * _nvram_get(const char *name); -extern int _nvram_set(const char *name, const char *value); -extern int _nvram_unset(const char *name); -extern int _nvram_getall(char *buf, int count); -extern int _nvram_commit(struct nvram_header *header); -extern int _nvram_init(void *sbh); -extern void _nvram_exit(void); - -/* Globals */ -static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED; -static struct semaphore nvram_sem; -static unsigned long nvram_offset = 0; -static int nvram_major = -1; -static devfs_handle_t nvram_handle = NULL; -static struct mtd_info *nvram_mtd = NULL; - -int -_nvram_read(char *buf) -{ -	struct nvram_header *header = (struct nvram_header *) buf; -	size_t len; - -	if (!nvram_mtd || -	    MTD_READ(nvram_mtd, nvram_mtd->size - NVRAM_SPACE, NVRAM_SPACE, &len, buf) || -	    len != NVRAM_SPACE || -	    header->magic != NVRAM_MAGIC) { -		/* Maybe we can recover some data from early initialization */ -		memcpy(buf, nvram_buf, NVRAM_SPACE); -	} - -	return 0; -} - -struct nvram_tuple * -_nvram_realloc(struct nvram_tuple *t, const char *name, const char *value) -{ -	if ((nvram_offset + strlen(value) + 1) > NVRAM_SPACE) -		return NULL; - -	if (!t) { -		if (!(t = kmalloc(sizeof(struct nvram_tuple) + strlen(name) + 1, GFP_ATOMIC))) -			return NULL; - -		/* Copy name */ -		t->name = (char *) &t[1]; -		strcpy(t->name, name); - -		t->value = NULL; -	} - -	/* Copy value */ -	if (!t->value || strcmp(t->value, value)) { -		t->value = &nvram_buf[nvram_offset]; -		strcpy(t->value, value); -		nvram_offset += strlen(value) + 1; -	} - -	return t; -} - -void -_nvram_free(struct nvram_tuple *t) -{ -	if (!t) -		nvram_offset = 0; -	else -		kfree(t); -} - -int -nvram_set(const char *name, const char *value) -{ -	unsigned long flags; -	int ret; -	struct nvram_header *header; - -	spin_lock_irqsave(&nvram_lock, flags); -	if ((ret = _nvram_set(name, value))) { -		/* Consolidate space and try again */ -		if ((header = kmalloc(NVRAM_SPACE, GFP_ATOMIC))) { -			if (_nvram_commit(header) == 0) -				ret = _nvram_set(name, value); -			kfree(header); -		} -	} -	spin_unlock_irqrestore(&nvram_lock, flags); - -	return ret; -} - -char * -real_nvram_get(const char *name) -{ -	unsigned long flags; -	char *value; - -	spin_lock_irqsave(&nvram_lock, flags); -	value = _nvram_get(name); -	spin_unlock_irqrestore(&nvram_lock, flags); - -	return value; -} - -char * -nvram_get(const char *name) -{ -	if (nvram_major >= 0) -		return real_nvram_get(name); -	else -		return early_nvram_get(name); -} - -int -nvram_unset(const char *name) -{ -	unsigned long flags; -	int ret; - -	spin_lock_irqsave(&nvram_lock, flags); -	ret = _nvram_unset(name); -	spin_unlock_irqrestore(&nvram_lock, flags); - -	return ret; -} - -static void -erase_callback(struct erase_info *done) -{ -	wait_queue_head_t *wait_q = (wait_queue_head_t *) done->priv; -	wake_up(wait_q); -} - -int -nvram_commit(void) -{ -	char *buf; -	size_t erasesize, len, magic_len; -	unsigned int i; -	int ret; -	struct nvram_header *header; -	unsigned long flags; -	u_int32_t offset; -	DECLARE_WAITQUEUE(wait, current); -	wait_queue_head_t wait_q; -	struct erase_info erase; -	u_int32_t magic_offset = 0; /* Offset for writing MAGIC # */ - -	if (!nvram_mtd) { -		printk("nvram_commit: NVRAM not found\n"); -		return -ENODEV; -	} - -	if (in_interrupt()) { -		printk("nvram_commit: not committing in interrupt\n"); -		return -EINVAL; -	} - -	/* Backup sector blocks to be erased */ -	erasesize = ROUNDUP(NVRAM_SPACE, nvram_mtd->erasesize); -	if (!(buf = kmalloc(erasesize, GFP_KERNEL))) { -		printk("nvram_commit: out of memory\n"); -		return -ENOMEM; -	} - -	down(&nvram_sem); - -	if ((i = erasesize - NVRAM_SPACE) > 0) { -		offset = nvram_mtd->size - erasesize; -		len = 0; -		ret = MTD_READ(nvram_mtd, offset, i, &len, buf); -		if (ret || len != i) { -			printk("nvram_commit: read error ret = %d, len = %d/%d\n", ret, len, i); -			ret = -EIO; -			goto done; -		} -		header = (struct nvram_header *)(buf + i); -		magic_offset = i + ((void *)&header->magic - (void *)header); -	} else { -		offset = nvram_mtd->size - NVRAM_SPACE; -		magic_offset = ((void *)&header->magic - (void *)header); -		header = (struct nvram_header *)buf; -	} - -	/* clear the existing magic # to mark the NVRAM as unusable  -		 we can pull MAGIC bits low without erase	*/ -	header->magic = NVRAM_CLEAR_MAGIC; /* All zeros magic */ - -	/* Unlock sector blocks (for Intel 28F320C3B flash) , 20060309 */ -	if(nvram_mtd->unlock) -		nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize); - -	ret = MTD_WRITE(nvram_mtd, offset + magic_offset, sizeof(header->magic),  -									&magic_len, (char *)&header->magic); -	if (ret || magic_len != sizeof(header->magic)) { -		printk("nvram_commit: clear MAGIC error\n"); -		ret = -EIO; -		goto done; -	} - -	header->magic = NVRAM_MAGIC; /* reset MAGIC before we regenerate the NVRAM, -																otherwise we'll have an incorrect CRC */ -	/* Regenerate NVRAM */ -	spin_lock_irqsave(&nvram_lock, flags); -	ret = _nvram_commit(header); -	spin_unlock_irqrestore(&nvram_lock, flags); -	if (ret) -		goto done; - -	/* Erase sector blocks */ -	init_waitqueue_head(&wait_q); -	for (; offset < nvram_mtd->size - NVRAM_SPACE + header->len; offset += nvram_mtd->erasesize) { -		erase.mtd = nvram_mtd; -		erase.addr = offset; -		erase.len = nvram_mtd->erasesize; -		erase.callback = erase_callback; -		erase.priv = (u_long) &wait_q; - -		set_current_state(TASK_INTERRUPTIBLE); -		add_wait_queue(&wait_q, &wait); - -		/* Unlock sector blocks */ -		if (nvram_mtd->unlock) -			nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize); - -		if ((ret = MTD_ERASE(nvram_mtd, &erase))) { -			set_current_state(TASK_RUNNING); -			remove_wait_queue(&wait_q, &wait); -			printk("nvram_commit: erase error\n"); -			goto done; -		} - -		/* Wait for erase to finish */ -		schedule(); -		remove_wait_queue(&wait_q, &wait); -	} - -	/* Write partition up to end of data area */ -	header->magic = NVRAM_INVALID_MAGIC; /* All ones magic */ -	offset = nvram_mtd->size - erasesize; -	i = erasesize - NVRAM_SPACE + header->len; -	ret = MTD_WRITE(nvram_mtd, offset, i, &len, buf); -	if (ret || len != i) { -		printk("nvram_commit: write error\n"); -		ret = -EIO; -		goto done; -	} - -	/* Now mark the NVRAM in flash as "valid" by setting the correct -		 MAGIC # */ -	header->magic = NVRAM_MAGIC; -	ret = MTD_WRITE(nvram_mtd, offset + magic_offset, sizeof(header->magic),  -									&magic_len, (char *)&header->magic); -	if (ret || magic_len != sizeof(header->magic)) { -		printk("nvram_commit: write MAGIC error\n"); -		ret = -EIO; -		goto done; -	} - -	/* -	 * Reading a few bytes back here will put the device -	 * back to the correct mode on certain flashes */ -	offset = nvram_mtd->size - erasesize; -	ret = MTD_READ(nvram_mtd, offset, 4, &len, buf); - - done: -	up(&nvram_sem); -	kfree(buf); - -	return ret; -} - -int -nvram_getall(char *buf, int count) -{ -	unsigned long flags; -	int ret; - -	spin_lock_irqsave(&nvram_lock, flags); -	if (nvram_major >= 0) -		ret = _nvram_getall(buf, count); -	else -		ret = early_nvram_getall(buf, count); -	spin_unlock_irqrestore(&nvram_lock, flags); - -	return ret; -} - - - - - - - -/* User mode interface below */ - -static ssize_t -dev_nvram_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ -	char tmp[100], *name = tmp, *value; -	ssize_t ret; -	unsigned long off; - -	if (count > sizeof(tmp)) { -		if (!(name = kmalloc(count, GFP_KERNEL))) -			return -ENOMEM; -	} - -	if (copy_from_user(name, buf, count)) { -		ret = -EFAULT; -		goto done; -	} - -	if (*name == '\0') { -		/* Get all variables */ -		ret = nvram_getall(name, count); -		if (ret == 0) { -			if (copy_to_user(buf, name, count)) { -				ret = -EFAULT; -				goto done; -			} -			ret = count; -		} -	} else { -		if (!(value = nvram_get(name))) { -			ret = 0; -			goto done; -		} - -		/* Provide the offset into mmap() space */ -		off = (unsigned long) value - (unsigned long) nvram_buf; - -		if (put_user(off, (unsigned long *) buf)) { -			ret = -EFAULT; -			goto done; -		} - -		ret = sizeof(unsigned long); -	} - -	flush_cache_all();	 -  -done: -	if (name != tmp) -		kfree(name); - -	return ret; -} - -static ssize_t -dev_nvram_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ -	char tmp[100], *name = tmp, *value; -	ssize_t ret; - -	if (count > sizeof(tmp)) { -		if (!(name = kmalloc(count, GFP_KERNEL))) -			return -ENOMEM; -	} - -	if (copy_from_user(name, buf, count)) { -		ret = -EFAULT; -		goto done; -	} - -	value = name; -	name = strsep(&value, "="); -	if (value) -		ret = nvram_set(name, value) ? : count; -	else -		ret = nvram_unset(name) ? : count; - - done: -	if (name != tmp) -		kfree(name); - -	return ret; -}	 - -static int -dev_nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ -	if (cmd != NVRAM_MAGIC) -		return -EINVAL; - -	return nvram_commit(); -} - -static int -dev_nvram_mmap(struct file *file, struct vm_area_struct *vma) -{ -	unsigned long offset = virt_to_phys(nvram_buf); - -	if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start, -			     vma->vm_page_prot)) -		return -EAGAIN; - -	return 0; -} - -static int -dev_nvram_open(struct inode *inode, struct file * file) -{ -	MOD_INC_USE_COUNT; -	return 0; -} - -static int -dev_nvram_release(struct inode *inode, struct file * file) -{ -	MOD_DEC_USE_COUNT; -	return 0; -} - -static struct file_operations dev_nvram_fops = { -	owner:		THIS_MODULE, -	open:		dev_nvram_open, -	release:	dev_nvram_release, -	read:		dev_nvram_read, -	write:		dev_nvram_write, -	ioctl:		dev_nvram_ioctl, -	mmap:		dev_nvram_mmap, -}; - -static void -dev_nvram_exit(void) -{ -	int order = 0; -	struct page *page, *end; - -	if (nvram_handle) -		devfs_unregister(nvram_handle); - -	if (nvram_major >= 0) -		devfs_unregister_chrdev(nvram_major, "nvram"); - -	if (nvram_mtd) -		put_mtd_device(nvram_mtd); - -	while ((PAGE_SIZE << order) < NVRAM_SPACE) -		order++; -	end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1); -	for (page = virt_to_page(nvram_buf); page <= end; page++) -		mem_map_unreserve(page); - -	_nvram_exit(); -} - -static int __init -dev_nvram_init(void) -{ -	int order = 0, ret = 0; -	struct page *page, *end; -	unsigned int i; - -	/* Allocate and reserve memory to mmap() */ -	while ((PAGE_SIZE << order) < NVRAM_SPACE) -		order++; -	end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1); -	for (page = virt_to_page(nvram_buf); page <= end; page++) -		mem_map_reserve(page); - -#ifdef CONFIG_MTD -	/* Find associated MTD device */ -	for (i = 0; i < MAX_MTD_DEVICES; i++) { -		nvram_mtd = get_mtd_device(NULL, i); -		if (nvram_mtd) { -			if (!strcmp(nvram_mtd->name, "nvram") && -			    nvram_mtd->size >= NVRAM_SPACE) -				break; -			put_mtd_device(nvram_mtd); -		} -	} -	if (i >= MAX_MTD_DEVICES) -		nvram_mtd = NULL; -#endif - -	/* Initialize hash table lock */ -	spin_lock_init(&nvram_lock); - -	/* Initialize commit semaphore */ -	init_MUTEX(&nvram_sem); - -	/* Register char device */ -	if ((nvram_major = devfs_register_chrdev(0, "nvram", &dev_nvram_fops)) < 0) { -		ret = nvram_major; -		goto err; -	} - -	/* Initialize hash table */ -	_nvram_init(sbh); - -	/* Create /dev/nvram handle */ -	nvram_handle = devfs_register(NULL, "nvram", DEVFS_FL_NONE, nvram_major, 0, -				      S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, &dev_nvram_fops, NULL); - -	/* Set the SDRAM NCDL value into NVRAM if not already done */ -	if (getintvar(NULL, "sdram_ncdl") == 0) { -		unsigned int ncdl; -		char buf[] = "0x00000000"; - -		if ((ncdl = sb_memc_get_ncdl(sbh))) { -			sprintf(buf, "0x%08x", ncdl); -			nvram_set("sdram_ncdl", buf); -			nvram_commit(); -		} -	} - -	return 0; - - err: -	dev_nvram_exit(); -	return ret; -} - -module_init(dev_nvram_init); -module_exit(dev_nvram_exit);  | 
