nvram [K26 part]: auto-detect the nvram size
[tomato.git] / release / src-rt / linux / linux-2.6 / arch / mips / brcm-boards / bcm947xx / nvram_linux.c
blob3d22929aa8985996cabc4faffb816f17477c409c
1 /*
2 * NVRAM variable manipulation (Linux kernel half)
4 * Copyright 2006, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
14 #include <linux/config.h>
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/string.h>
19 #include <linux/interrupt.h>
20 #include <linux/spinlock.h>
21 #include <linux/slab.h>
22 #include <linux/bootmem.h>
23 #include <linux/fs.h>
24 #include <linux/miscdevice.h>
25 #include <linux/mtd/mtd.h>
26 #include <asm/addrspace.h>
27 #include <asm/io.h>
28 #include <asm/uaccess.h>
30 #include <typedefs.h>
31 #include <osl.h>
32 #include <bcmendian.h>
33 #include <bcmnvram.h>
34 #include <bcmutils.h>
35 #include <sbconfig.h>
36 #include <sbchipc.h>
37 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
38 #include <siutils.h>
39 #else // K24
40 #include <linux/wrapper.h>
41 #include <sbutils.h>
42 #endif
43 #include <hndmips.h>
44 #include <sflash.h>
45 #include <linux/vmalloc.h>
47 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
48 #include <asm/cacheflush.h>
49 #include <bcmdefs.h>
50 #include <hndsoc.h>
51 #include <linux/nls.h>
52 #ifdef MODULE
53 /* This isn't right, but I can't figure out how to make the link error go away. */
54 #define flush_cache_all() do { hndcrc8(nvram_buf, sizeof(nvram_buf), 0); hndcrc8(nvram_buf, sizeof(nvram_buf), 0); } while (0)
55 #endif
56 #endif // K26
58 MODULE_LICENSE("GPL");
60 #define KB * 1024
62 static int hdr_valid(struct nvram_header *header, int max);
64 /* In BSS to minimize text size and page aligned so it can be mmap()-ed */
65 /* Used for:
66 * In early... as nvram (read) staging buffer.
67 * In normal.. to hold the values of items.
69 char nvram_buf[NVRAM_VAL_SIZE] __attribute__((aligned(PAGE_SIZE)));
71 /* This is the staging buffer for data going to/from the flash.
72 * Also as work buffer for compactify.
73 * It is large enough to hold all the NVRAM data and is 1 or more EBs is size.
74 * The first chunk (before the nvram areaa) in the flash eb is preserved. */
75 unsigned char *nvram_commit_buf = NULL;
76 static int erasesize; /* The size of flash eraseblock & commit_buf.
77 * 32KB rounded up to mtd->erasesise. (64KB or 128KB) */
79 int oflow_area_present = 0;
81 /* The nvram area is the last 32KB (or 60kb for E3000) of the last eraseblock of the flash chip.
82 * Normally this is the mtdN partition named "nvram".
83 * Normally this paritition is the entire last eraseblock. Do "cat /proc/mtd" to see this.
84 * The first part of the last EB, from the start up to the NVRAM area, is
85 * not used by pmon/cfe.
86 * We use the next-to-last 32kb for overflow (extended) nvram area. On a
87 * smallish flash chip these 2 areas are the entire EB. Some larger routers
88 * have 128KB EB size, and on these the 1st 64KB of the last EB is unused.
90 * The implementation of this code is one main area of 32KB and one oflow area
91 * of 32KB, for a total available nvram of 64KB.
92 * Period.
94 * Some routers have pmon/cfe that uses 60KB for nvram. On these, there is no
95 * overflow area. The total nvram area of these is 60kb.
99 #if NVRAM_SPACE != (32 * 1024)
100 #error Attempt to redefine NVRAM_SPACE to something other than 32K.
101 #endif
103 /* This is the size of pmon/cfe (and for us: "main") nvram area.
104 * Normally 32kb, but a few routers it is 60kb.
106 int nvram_space = NVRAM_32K; /* Determined at probe time. */
108 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
109 #define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
110 #define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args)
111 #define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args)
113 #define mem_map_reserve(a) SetPageReserved(a)
114 #define mem_map_unreserve(a) ClearPageReserved(a)
116 #define bcm947xx_sbh bcm947xx_sih
117 extern void *bcm947xx_sih;
119 #define sb_setcore si_setcore
120 #define SB_CC CC_CORE_ID
121 #define SB_FLASH2_SZ SI_FLASH2_SZ
122 #define SB_FLASH1_SZ SI_FLASH1_SZ
123 #define SB_FLASH1 SI_FLASH1
124 #define SB_FLASH2 SI_FLASH2
125 #define SB_BUS SI_BUS
126 #define sb_setosh si_setosh
127 #define sb_memc_get_ncdl si_memc_get_ncdl
129 #define sih bcm947xx_sih
130 #endif // KERNEL 2.6
132 #if 0
133 static int
134 nvram_valid(struct nvram_header *header)
136 return
137 header->magic == NVRAM_MAGIC &&
138 header->len >= sizeof(struct nvram_header) &&
139 header->len <= NVRAM_SPACE &&
140 #ifdef MIPSEB
141 1; /* oleg -- no crc check for now */
142 #else
143 (header->crc_ver_init & 255) ==
144 hndcrc8((char *) header + NVRAM_CRC_START_POSITION,
145 header->len - NVRAM_CRC_START_POSITION, CRC8_INIT_VALUE);
146 #endif
148 #endif
150 #ifdef MODULE
152 #define early_nvram_get(name) nvram_get(name)
153 #define early_nvram_getall(name,c) _nvram_getall(name,c)
154 extern void *bcm947xx_sbh;
155 #define sbh bcm947xx_sbh
156 #define sbh_lock bcm947xx_sbh_lock
158 #define NVR_DEVNAME "nvram2"
159 #define NVR_DEVNUM 1
161 #else /* !MODULE */
162 #define NVR_DEVNAME "nvram"
163 #define NVR_DEVNUM 0
165 /* Global SB handle */
166 extern void *bcm947xx_sbh;
167 extern spinlock_t bcm947xx_sbh_lock;
169 /* Convenience */
170 #define sbh bcm947xx_sbh
171 #define sbh_lock bcm947xx_sbh_lock
173 /* Early (before mm or mtd) read-only access to NVRAM */
174 /* Probe for NVRAM header */
175 static void __init
176 early_nvram_init(void)
178 struct nvram_header *header;
179 chipcregs_t *cc;
180 struct sflash *info = NULL;
181 int i;
182 int j;
183 uint32 base, off, lim;
184 u32 *src, *dst;
186 if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) {
187 base = KSEG1ADDR(SB_FLASH2);
188 switch (readl(&cc->capabilities) & CC_CAP_FLASH_MASK) {
189 case PFLASH:
190 lim = SB_FLASH2_SZ;
191 break;
193 case SFLASH_ST:
194 case SFLASH_AT:
195 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
196 if ((info = sflash_init(sih, cc)) == NULL)
197 return;
198 #else
199 if ((info = sflash_init(cc)) == NULL)
200 return;
201 #endif
202 lim = info->size;
203 break;
205 case FLASH_NONE:
206 default:
207 return;
209 } else {
210 /* extif assumed, Stop at 4 MB */
211 base = KSEG1ADDR(SB_FLASH1);
212 lim = SB_FLASH1_SZ;
215 /* XXX: hack for supporting the CFE environment stuff on WGT634U */
216 src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000);
217 dst = (u32 *) nvram_buf;
218 if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) {
219 printk("early_nvram_init: WGT634U NVRAM found.\n");
221 for (i = 0; i < 0x1ff0; i++) {
222 if (*src == 0xFFFFFFFF)
223 break;
224 *dst++ = *src++;
226 return;
229 off = FLASH_MIN;
230 while (off <= lim) {
231 /* Windowed flash access */
232 j = 32 KB;
233 header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_32K);
234 if (hdr_valid(header, NVRAM_32K))
235 goto found;
236 j = 4 KB;
237 header = (struct nvram_header *) KSEG1ADDR(base + off - (NVRAM_32K + 28 KB));
238 if (hdr_valid(header, NVRAM_32K + 28 KB))
239 goto found;
240 off <<= 1;
243 printk("Probing didn't find nvram, assuming 32K.\n");
244 j = 32 KB;
245 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
246 header = (struct nvram_header *) KSEG1ADDR(base + 4 KB);
247 if (header->magic == NVRAM_MAGIC)
248 goto found;
250 header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
251 if (header->magic == NVRAM_MAGIC)
252 goto found;
254 printk("early_nvram_init: NVRAM not found\n");
255 return;
257 found:
258 src = (u32 *) header;
259 dst = (u32 *) nvram_buf;
260 nvram_space = 64 KB - j;
261 printk("early_nvram_init detected %d KB NVRAM area\n", nvram_space/1024);
262 bzero(nvram_buf, sizeof(nvram_buf));
263 for (i = 0; i < sizeof(struct nvram_header); i += 4)
264 *dst++ = *src++;
265 for (; i < header->len && i < nvram_space; i += 4)
266 *dst++ = *src++;
269 /* Early (before mm or mtd) read-only access to NVRAM */
270 static char * __init
271 early_nvram_get(const char *name)
273 char *var, *value, *end, *eq;
275 if (!name)
276 return NULL;
278 /* Too early? */
279 if (sbh == NULL)
280 return NULL;
282 if (!nvram_buf[0])
283 early_nvram_init();
285 /* Look for name=value and return value */
286 var = &nvram_buf[sizeof(struct nvram_header)];
287 end = nvram_buf + sizeof(nvram_buf) - 2;
288 end[0] = end[1] = '\0';
289 for (; *var; var = value + strlen(value) + 1) {
290 if (!(eq = strchr(var, '=')))
291 break;
292 value = eq + 1;
293 if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
294 return value;
297 return NULL;
300 static int __init
301 early_nvram_getall(char *buf, int count)
303 char *var, *end;
304 int len = 0;
306 /* Too early? */
307 if (sbh == NULL)
308 return -1;
310 if (!nvram_buf[0])
311 early_nvram_init();
313 bzero(buf, count);
315 /* Write name=value\0 ... \0\0 */
316 var = &nvram_buf[sizeof(struct nvram_header)];
317 end = nvram_buf + sizeof(nvram_buf) - 2;
318 end[0] = end[1] = '\0';
319 for (; *var; var += strlen(var) + 1) {
320 if ((count - len) <= (strlen(var) + 1))
321 break;
322 len += sprintf(buf + len, "%s", var) + 1;
325 return 0;
327 #endif /* !MODULE */
329 extern char * _nvram_get(const char *name);
330 extern int _nvram_set(const char *name, const char *value);
331 extern int _nvram_unset(const char *name);
332 extern int _nvram_getall(char *buf, int count);
333 extern int _nvram_commit(struct nvram_header *header);
334 extern int _nvram_init(void *sbh);
335 extern void _nvram_exit(void);
337 /* Globals */
338 static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED;
339 static struct semaphore nvram_sem;
340 static int nvram_major = -1;
341 static struct mtd_info *nvram_mtd = NULL;
342 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
343 static struct class *nvram_class = NULL;
344 #else
345 static devfs_handle_t nvram_handle = NULL;
346 #endif
348 static int
349 hdr_valid(struct nvram_header *header, int max)
351 return (header->magic == NVRAM_MAGIC &&
352 header->len >= sizeof(struct nvram_header) &&
353 header->len <= max &&
354 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
355 (nvram_calc_crc(header) == (uint8) header->crc_ver_init));
356 #else
357 (header->crc_ver_init & 255) ==
358 hndcrc8((char *) header + NVRAM_CRC_START_POSITION,
359 header->len - NVRAM_CRC_START_POSITION, CRC8_INIT_VALUE);
360 #endif
363 #if 0
365 _nvram_read(char *buf)
367 struct nvram_header *header = (struct nvram_header *) buf;
368 size_t len;
370 if (!nvram_mtd ||
371 MTD_READ(nvram_mtd, nvram_mtd->size - nvram_space, nvram_space, &len, buf) ||
372 len != nvram_space ||
373 !nvram_valid(header)) {
374 printk("_nvram_read: invalid nvram image\n");
375 /* Maybe we can recover some data from early initialization */
376 memcpy(buf, nvram_buf, nvram_space);
379 return 0;
381 #endif
383 /* Read the entire /dev/nvram block. Works only if EB is >= 32KB.
384 * Uses the beginning of commit_buf.
385 * Returns: < 0 for error.
386 * >= 0 -- offset into nvram_commit_buf of the NVRAM header.
387 * N.B., nvram_commit_buf[] has the last 64KB of the flash nvram partition.
390 _nvram_init_read(void)
392 size_t len;
393 int j;
394 int ret;
395 struct nvram_header *header;
396 u_int32_t offset; /* fseek position of the last EB in the /mtd/nvram partition. */
397 unsigned int i;
399 if (!nvram_mtd) {
400 printk("nvram_init: NVRAM not found\n");
401 return -ENODEV;
404 oflow_area_present = 0;
405 if (erasesize < 2 * NVRAM_32K)
406 return -ENODEV;
408 i = 2 * NVRAM_32K;
409 /* seek offset to the last 64KB. Normally 0. 64k on 128k EB size. */
410 offset = nvram_mtd->size - i;
411 len = 0;
412 /* Read the last 64kb of flash */
413 ret = MTD_READ(nvram_mtd, offset, i, &len, nvram_commit_buf);
414 if (ret || len != i) {
415 printk("nvram_init: read error ret = %d, len = %d/%d\n", ret, len, i);
416 return -EIO;
418 /* Probe various spots to find the header. Every 4K down from 32K from the end.*/
419 for (j = 32 KB; j >= 0 ; j -= 4 KB) {
420 header = (struct nvram_header *)(nvram_commit_buf + j);
421 if (hdr_valid(header, 64 KB - j))
422 break;
424 if (j >= 0)
425 printk("Probing found nvram header at %dK, size %dK\n", (j)/1024, (64 KB - j)/1024);
426 else {
427 printk("Probing didn't find nvram header. Assuming 32K\n");
428 j = 32 KB;
430 nvram_space = 64 KB - j;
431 return j;
435 /* Called in early initialization. */
437 nvram_init(void *sbh)
439 return 0;
443 nvram_set(const char *name, const char *value)
445 unsigned long flags;
446 int ret;
448 spin_lock_irqsave(&nvram_lock, flags);
449 ret = _nvram_set(name, value);
450 spin_unlock_irqrestore(&nvram_lock, flags);
452 return ret;
455 char *
456 real_nvram_get(const char *name)
458 unsigned long flags;
459 char *value;
461 spin_lock_irqsave(&nvram_lock, flags);
462 value = _nvram_get(name);
463 spin_unlock_irqrestore(&nvram_lock, flags);
465 return value;
468 char *
469 nvram_get(const char *name)
471 if (nvram_major >= 0)
472 return real_nvram_get(name);
473 else
474 return early_nvram_get(name);
478 nvram_unset(const char *name)
480 unsigned long flags;
481 int ret;
483 spin_lock_irqsave(&nvram_lock, flags);
484 ret = _nvram_unset(name);
485 spin_unlock_irqrestore(&nvram_lock, flags);
487 return ret;
490 static void
491 erase_callback(struct erase_info *done)
493 wait_queue_head_t *wait_q = (wait_queue_head_t *) done->priv;
494 wake_up(wait_q);
498 nvram_commit(void)
500 size_t erasesize, len, magic_len;
501 unsigned int i;
502 int ret;
503 struct nvram_header *header;
504 unsigned long flags;
505 u_int32_t offset;
506 DECLARE_WAITQUEUE(wait, current);
507 wait_queue_head_t wait_q;
508 struct erase_info erase;
509 u_int32_t magic_offset = 0; /* Offset for writing MAGIC # */
511 if (!nvram_mtd) {
512 printk("nvram_commit: NVRAM not found\n");
513 return -ENODEV;
516 if (in_interrupt()) {
517 printk("nvram_commit: not committing in interrupt\n");
518 return -EINVAL;
521 /* Backup sector blocks to be erased */
522 erasesize = ROUNDUP(nvram_space, nvram_mtd->erasesize);
523 down(&nvram_sem);
525 //#warning no commit
526 //_nvram_commit(nvram_commit_buf); ret = -ENODEV; goto done; //temp!!!
528 if ((i = erasesize - nvram_space) > 0) {
529 offset = nvram_mtd->size - erasesize;
530 len = 0;
531 ret = MTD_READ(nvram_mtd, offset, i, &len, nvram_commit_buf);
532 if (ret || len != i) {
533 printk("nvram_commit: read error ret = %d, len = %d/%d\n", ret, len, i);
534 ret = -EIO;
535 goto done;
538 else {
539 offset = nvram_mtd->size - nvram_space;
540 i = 0;
542 header = (struct nvram_header *)(nvram_commit_buf + i);
543 magic_offset = i + offsetof(struct nvram_header, magic);
545 /* clear the existing magic # to mark the NVRAM as unusable
546 * we can pull MAGIC bits low without erase
548 header->magic = NVRAM_CLEAR_MAGIC; /* All zeros magic */
550 /* Unlock sector blocks (for Intel 28F320C3B flash) , 20060309 */
551 if (nvram_mtd->unlock)
552 nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize);
554 ret = MTD_WRITE(nvram_mtd, offset + magic_offset, sizeof(header->magic),
555 &magic_len, (char *)&header->magic);
556 if (ret || magic_len != sizeof(header->magic)) {
557 printk("nvram_commit: clear MAGIC error\n");
558 ret = -EIO;
559 goto done;
562 /* reset MAGIC before we regenerate the NVRAM,
563 * otherwise we'll have an incorrect CRC
565 header->magic = NVRAM_MAGIC;
566 /* Regenerate NVRAM */
567 spin_lock_irqsave(&nvram_lock, flags);
568 ret = _nvram_commit(header);
569 spin_unlock_irqrestore(&nvram_lock, flags);
570 if (ret)
571 goto done;
573 /* Erase sector blocks */
574 init_waitqueue_head(&wait_q);
575 for (; offset < nvram_mtd->size - nvram_space + header->len; offset += nvram_mtd->erasesize) {
576 erase.mtd = nvram_mtd;
577 erase.addr = offset;
578 erase.len = nvram_mtd->erasesize;
579 erase.callback = erase_callback;
580 erase.priv = (u_long) &wait_q;
582 set_current_state(TASK_INTERRUPTIBLE);
583 add_wait_queue(&wait_q, &wait);
585 /* Unlock sector blocks */
586 if (nvram_mtd->unlock)
587 nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize);
589 if ((ret = MTD_ERASE(nvram_mtd, &erase))) {
590 set_current_state(TASK_RUNNING);
591 remove_wait_queue(&wait_q, &wait);
592 printk("nvram_commit: erase error\n");
593 goto done;
596 /* Wait for erase to finish */
597 schedule();
598 remove_wait_queue(&wait_q, &wait);
601 /* Write partition up to end of data area */
602 header->magic = NVRAM_INVALID_MAGIC; /* All ones magic */
603 offset = nvram_mtd->size - erasesize;
604 i = erasesize - nvram_space + header->len;
605 ret = MTD_WRITE(nvram_mtd, offset, i, &len, nvram_commit_buf);
606 if (ret || len != i) {
607 printk("nvram_commit: write error\n");
608 ret = -EIO;
609 goto done;
612 /* Now mark the NVRAM in flash as "valid" by setting the correct MAGIC # */
613 header->magic = NVRAM_MAGIC;
614 ret = MTD_WRITE(nvram_mtd, offset + magic_offset, sizeof(header->magic),
615 &magic_len, (char *)&header->magic);
616 if (ret || magic_len != sizeof(header->magic)) {
617 printk("nvram_commit: write MAGIC error\n");
618 ret = -EIO;
619 goto done;
623 * Reading a few bytes back here will put the device
624 * back to the correct mode on certain flashes
626 offset = nvram_mtd->size - erasesize;
627 ret = MTD_READ(nvram_mtd, offset, 4, &len, nvram_commit_buf);
629 done:
630 up(&nvram_sem);
631 return ret;
635 nvram_getall(char *buf, int count)
637 unsigned long flags;
638 int ret;
640 spin_lock_irqsave(&nvram_lock, flags);
641 if (nvram_major >= 0)
642 ret = _nvram_getall(buf, count);
643 else
644 ret = early_nvram_getall(buf, count);
645 spin_unlock_irqrestore(&nvram_lock, flags);
647 return ret;
650 #ifndef MODULE
651 EXPORT_SYMBOL(nvram_get);
652 EXPORT_SYMBOL(nvram_getall);
653 EXPORT_SYMBOL(nvram_set);
654 EXPORT_SYMBOL(nvram_unset);
655 EXPORT_SYMBOL(nvram_commit);
656 #endif
658 /* User mode interface below */
660 static ssize_t
661 dev_nvram_read(struct file *file, char *buf, size_t count, loff_t *ppos)
663 char tmp[100], *name = tmp, *value;
664 ssize_t ret;
665 unsigned long off;
667 if (count > sizeof(tmp)) {
668 if (!(name = kmalloc(count, GFP_KERNEL)))
669 return -ENOMEM;
672 if (copy_from_user(name, buf, count)) {
673 ret = -EFAULT;
674 goto done;
677 if (*name == '\0') {
678 /* Get all variables */
679 ret = nvram_getall(name, count);
680 if (ret == 0) {
681 if (copy_to_user(buf, name, count)) {
682 ret = -EFAULT;
683 goto done;
685 ret = count;
687 } else {
688 if (!(value = nvram_get(name))) {
689 ret = 0;
690 goto done;
693 /* Provide the offset into mmap() space */
694 off = (unsigned long) value - (unsigned long) nvram_buf;
696 if (put_user(off, (unsigned long *) buf)) {
697 ret = -EFAULT;
698 goto done;
701 ret = sizeof(char *);
704 flush_cache_all();
706 done:
707 if (name != tmp)
708 kfree(name);
710 return ret;
713 static ssize_t
714 dev_nvram_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
716 char tmp[100], *name = tmp, *value;
717 ssize_t ret;
719 if (count > sizeof(tmp)) {
720 if (!(name = kmalloc(count, GFP_KERNEL)))
721 return -ENOMEM;
724 if (copy_from_user(name, buf, count)) {
725 ret = -EFAULT;
726 goto done;
729 value = name;
730 name = strsep(&value, "=");
731 if (value)
732 ret = nvram_set(name, value) ? : count;
733 else
734 ret = nvram_unset(name) ? : count;
736 done:
737 if (name != tmp)
738 kfree(name);
740 return ret;
743 static int
744 dev_nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
746 if (cmd != NVRAM_MAGIC)
747 return -EINVAL;
749 return nvram_commit();
752 #ifdef MODULE
753 /* This maps the vmalloced module buffer to user space. */
755 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
756 static int do_vm_mmap(struct vm_area_struct *vma, char *adr, unsigned long siz)
758 unsigned int start = vma->vm_start;
759 int pfn;
760 int ret;
762 while (siz > 0) {
763 pfn = vmalloc_to_pfn(adr);
764 if ((ret = remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_READONLY)) < 0) {
765 return ret;
767 start += PAGE_SIZE;
768 adr += PAGE_SIZE;
769 siz -= PAGE_SIZE;
772 return 0;
775 #else // K24
776 /* From bttv-driver.c
777 * Here we want the physical address of the memory.
778 * This is used when initializing the contents of the
779 * area and marking the pages as reserved.
781 static inline unsigned long kvirt_to_pa(unsigned long adr)
783 unsigned long kva;
785 kva = (unsigned long)page_address(vmalloc_to_page((void *)adr));
786 kva |= adr & (PAGE_SIZE-1); /* restore the offset */
787 return __pa(kva);
790 static int do_vm_mmap(struct vm_area_struct *vma, char *adr, unsigned long siz)
792 unsigned int start = vma->vm_start;
793 unsigned long page;
795 while (siz > 0) {
796 page = kvirt_to_pa((unsigned long)adr);
797 if (remap_page_range(start, page, PAGE_SIZE, PAGE_READONLY))
798 return -EAGAIN;
799 start += PAGE_SIZE;
800 adr += PAGE_SIZE;
801 siz -= PAGE_SIZE;
803 return 0;
805 #endif
806 #endif // MODULE
808 static int
809 dev_nvram_mmap(struct file *file, struct vm_area_struct *vma)
811 unsigned long siz = vma->vm_end - vma->vm_start;
813 if (siz > NVRAM_VAL_SIZE) siz = NVRAM_VAL_SIZE;
814 #ifdef MODULE
815 return (do_vm_mmap(vma, nvram_buf, siz));
816 #else
817 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
818 if (remap_pfn_range(vma, vma->vm_start,
819 __pa(nvram_buf) >> PAGE_SHIFT,
820 siz, vma->vm_page_prot))
821 return -EAGAIN;
822 #else
823 if (remap_page_range(vma->vm_start, virt_to_phys(nvram_buf),
824 siz, vma->vm_page_prot))
825 return -EAGAIN;
826 #endif
827 return 0;
828 #endif
831 static int
832 dev_nvram_open(struct inode *inode, struct file * file)
834 MOD_INC_USE_COUNT;
835 return 0;
838 static int
839 dev_nvram_release(struct inode *inode, struct file * file)
841 MOD_DEC_USE_COUNT;
842 return 0;
845 static struct file_operations dev_nvram_fops = {
846 owner: THIS_MODULE,
847 open: dev_nvram_open,
848 release: dev_nvram_release,
849 read: dev_nvram_read,
850 write: dev_nvram_write,
851 ioctl: dev_nvram_ioctl,
852 mmap: dev_nvram_mmap
855 static void
856 dev_nvram_exit(void)
858 #ifndef MODULE
859 int order = 0;
860 struct page *page, *end;
861 #else
862 char *adr = nvram_buf;
863 int size = NVRAM_VAL_SIZE;
864 #endif
866 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
867 if (nvram_handle)
868 devfs_unregister(nvram_handle);
870 if (nvram_major >= 0)
871 devfs_unregister_chrdev(nvram_major, NVR_DEVNAME);
872 #else // K26
873 if (nvram_class) {
874 class_device_destroy(nvram_class, MKDEV(nvram_major, NVR_DEVNUM));
875 class_destroy(nvram_class);
878 if (nvram_major >= 0)
879 unregister_chrdev(nvram_major, NVR_DEVNAME);
880 #endif
881 if (nvram_mtd)
882 put_mtd_device(nvram_mtd);
884 #ifndef MODULE
885 while ((PAGE_SIZE << order) < NVRAM_VAL_SIZE)
886 order++;
887 end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1);
888 for (page = virt_to_page(nvram_buf); page <= end; page++)
889 mem_map_unreserve(page);
890 #else
891 while (size > 0) {
892 mem_map_unreserve(vmalloc_to_page((void *)adr));
893 adr += PAGE_SIZE;
894 size -= PAGE_SIZE;
896 #endif
897 _nvram_exit();
898 vfree(nvram_commit_buf);
901 static int __init
902 dev_nvram_init(void)
904 int ret = 0;
905 unsigned int i;
906 osl_t *osh;
907 #ifndef MODULE
908 int order = 0;
909 struct page *page, *end;
910 #else
911 char *adr = nvram_buf;
912 int size = NVRAM_VAL_SIZE;
913 #endif
915 //printk("---------------------------------------------------------\n");
916 printk("----nvram loading -----" __DATE__ " " __TIME__ " --------\n");
917 #ifndef MODULE
918 /* Allocate and reserve memory to mmap() */
919 while ((PAGE_SIZE << order) < NVRAM_VAL_SIZE)
920 order++;
921 end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1);
922 for (page = virt_to_page(nvram_buf); page <= end; page++)
923 mem_map_reserve(page);
924 #else
925 while (size > 0) {
926 mem_map_reserve(vmalloc_to_page((void *)adr));
927 adr += PAGE_SIZE;
928 size -= PAGE_SIZE;
930 #endif
932 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
933 #ifdef CONFIG_MTD
934 /* Find associated MTD device */
935 for (i = 0; i < MAX_MTD_DEVICES; i++) {
936 nvram_mtd = get_mtd_device(NULL, i);
937 if (nvram_mtd) {
938 if (!strcmp(nvram_mtd->name, "nvram") &&
939 nvram_mtd->size >= NVRAM_32K)
940 break;
941 put_mtd_device(nvram_mtd);
944 if (i >= MAX_MTD_DEVICES)
945 nvram_mtd = NULL;
946 #endif
948 /* Initialize hash table lock */
949 spin_lock_init(&nvram_lock);
951 /* Initialize commit semaphore */
952 init_MUTEX(&nvram_sem);
954 /* Register char device */
955 if ((nvram_major = devfs_register_chrdev(0, NVR_DEVNAME, &dev_nvram_fops)) < 0) {
956 ret = nvram_major;
957 goto err;
960 if (sb_osh(sbh) == NULL) {
961 osh = osl_attach(NULL, SB_BUS, FALSE);
962 if (osh == NULL) {
963 printk("Error allocating osh\n");
964 goto err;
966 sb_setosh(sbh, osh);
969 /* Create /dev/nvram handle */
970 nvram_handle = devfs_register(NULL, NVR_DEVNAME, DEVFS_FL_NONE, nvram_major, NVR_DEVNUM,
971 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, &dev_nvram_fops, NULL);
973 #else // KERNEL 2.6
974 #if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
975 /* Find associated MTD device */
976 for (i = 0; i < MAX_MTD_DEVICES; i++) {
977 nvram_mtd = get_mtd_device(NULL, i);
978 if (!IS_ERR(nvram_mtd)) {
979 if (!strcmp(nvram_mtd->name, "nvram") &&
980 nvram_mtd->size >= NVRAM_32K) {
981 break;
983 put_mtd_device(nvram_mtd);
986 if (i >= MAX_MTD_DEVICES)
987 nvram_mtd = NULL;
988 #endif
990 /* Initialize hash table lock */
991 spin_lock_init(&nvram_lock);
993 /* Initialize commit semaphore */
994 init_MUTEX(&nvram_sem);
996 /* Register char device */
997 if ((nvram_major = register_chrdev(0, NVR_DEVNAME, &dev_nvram_fops)) < 0) {
998 ret = nvram_major;
999 goto err;
1002 if (si_osh(sih) == NULL) {
1003 osh = osl_attach(NULL, SI_BUS, FALSE);
1004 if (osh == NULL) {
1005 printk("Error allocating osh\n");
1006 unregister_chrdev(nvram_major, NVR_DEVNAME);
1007 goto err;
1009 si_setosh(sih, osh);
1012 /* Create /dev/nvram handle */
1013 nvram_class = class_create(THIS_MODULE, NVR_DEVNAME);
1014 if (IS_ERR(nvram_class)) {
1015 printk("Error creating nvram class\n");
1016 goto err;
1019 /* Add the device nvram0 */
1020 class_device_create(nvram_class, NULL, MKDEV(nvram_major, NVR_DEVNUM), NULL, NVR_DEVNAME);
1021 #endif
1023 /* reserve commit read buffer */
1024 /* Backup sector blocks to be erased */
1025 erasesize = ROUNDUP(NVRAM_VAL_SIZE, nvram_mtd->erasesize);
1026 if (!(nvram_commit_buf = vmalloc(erasesize))) {
1027 printk("dev_nvram_init: nvram_commit_buf out of memory\n");
1028 goto err;
1031 /* Initialize the in-memory database */
1032 _nvram_init(sbh);
1034 /* Set the SDRAM NCDL value into NVRAM if not already done */
1035 if (getintvar(NULL, "sdram_ncdl") == 0) {
1036 unsigned int ncdl;
1037 char buf[16];
1039 if ((ncdl = sb_memc_get_ncdl(sbh))) {
1040 sprintf(buf, "0x%08x", ncdl);
1041 nvram_set("sdram_ncdl", buf);
1042 nvram_commit();
1046 return 0;
1047 err:
1048 dev_nvram_exit();
1049 return ret;
1052 module_init(dev_nvram_init);
1053 module_exit(dev_nvram_exit);
1055 /* For the emacs code formatting
1056 Local Variables:
1057 c-basic-offset: 8
1058 End: