nvram merge patch...
Ani Joshi
ajoshi at shell.unixbox.com
Thu Mar 9 02:53:05 EST 2000
with all the recent talk about nvram, i decide to try and merge the pmac
nvram stuff (and eventually prep also) into drivers/char/nvram.c. nvram.c
uses an "api" for PC and amiga, and i've added some pmacnvram support in
there. along with the basic nvram support of /dev/nvram, i've added
support for /proc/nvram which will dump the current variables and values.
note: this patch was hacked up late last nite and is no way belived to be
working, i want to get some feedback before continuing this. would this
be The Right solution?
when this is refined and finished, it will remove the need for
drivers/macintosh/nvram.c and arch/ppc/kernel/{pmac,prep}_nvram.c (though
i have not put in the necessary prep stuff in yet, just pmac)
any ideas/suggestions?
ani
-------------- next part --------------
--- nvram.c.orig Wed Mar 8 01:00:06 2000
+++ nvram.c Wed Mar 8 02:43:44 2000
@@ -34,12 +34,15 @@
#define PC 1
#define ATARI 2
+#define PMAC 3
/* select machine configuration */
#if defined(CONFIG_ATARI)
#define MACH ATARI
#elif defined(__i386__) || defined(__arm__) /* and others?? */
#define MACH PC
+#elif defined(CONFIG_PMAC)
+#define MACH PMAC
#else
#error Cannot build nvram driver for this machine configuration.
#endif
@@ -56,6 +59,7 @@
#define mach_check_checksum pc_check_checksum
#define mach_set_checksum pc_set_checksum
+#define mach_init /* nothing to do */
#define mach_proc_infos pc_proc_infos
#endif
@@ -76,10 +80,97 @@
#define mach_check_checksum atari_check_checksum
#define mach_set_checksum atari_set_checksum
+#define mach_init /* nothing to do */
#define mach_proc_infos atari_proc_infos
#endif
+#if MACH == PMAC
+
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/init.h>
+
+struct nvram {
+ unsigned short magic;
+ unsigned char char2;
+ unsigned char char3;
+ unsigned short cksum;
+ unsigned short end_vals;
+ unsigned short start_strsl
+ unsigned short word5;
+ unsigned long bits;
+ unsigned long vals[1];
+};
+
+struct nvbuf {
+ struct nvram nv;
+ car c[NVRAM_SIZE2];
+ unsigned short s[NVRAM_SIZE2/2];
+} nv_buffer;
+
+enum nv_type {
+ boolean,
+ word,
+ string
+};
+
+struct nv_var {
+ const char *name;
+ enum nv_type type;
+} nv_vars[] = {
+ {"little-endian?", boolean},
+ {"real-mode?", boolean},
+ {"auto-boot?", boolean},
+ {"diag-switch?", boolean},
+ {"fcode-debug?", boolean},
+ {"oem-banner?", boolean},
+ {"oem-logo?", boolean},
+ {"use-nvramrc?", boolean},
+ {"real-base", word},
+ {"real-size", word},
+ {"virt-base", word},
+ {"virt-size", word},
+ {"load-base", word},
+ {"pci-probe-list", word},
+ {"screen-#columns", word},
+ {"screen-#rows", word},
+ {"selftest-#megs", word},
+ {"boot-device", string},
+ {"boot-file", string},
+ {"diag-device", string},
+ {"diag-file", string},
+ {"input-device", string},
+ {"output-device", string},
+ {"oem-banner", string},
+ {"oem-logo", string},
+ {"nvramrc", string},
+ {"boot-command", string},
+};
+
+union nv_val {
+ unsigned long word_val;
+ char *str_val;
+} nv_vals[32];
+
+
+#define mach_check_checksum /* nothing to do ? */
+#define mach_set_checksum /* nothing to do ? */
+#define mach_init pmac_init
+#define mach_proc_infos pmac_proc_infos
+
+static int nvram_addrs, nvram_mult, is_core_99;
+static volatile unsigned char *nvram_addr;
+static volatile unsigned char *nvram_data;
+static char *nvram_image;
+static char nvstrbuf[NVRAM_SIZE2];
+static int nvstr_used = 0;
+
+#define NVRAM_SIZE 0x2000 /* 8kb of non-volatile RAM */
+#define NVRAM_SIZE2 0x800
+
+#endif
+
/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
* interrupts disabled. 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
@@ -113,6 +204,7 @@
static int mach_check_checksum( void );
static void mach_set_checksum( void );
+static void mach_init( void );
#ifdef CONFIG_PROC_FS
static int mach_proc_infos( unsigned char *contents, char *buffer, int *len,
off_t *begin, off_t offset, int size );
@@ -205,6 +297,115 @@
#endif /* MACH == ATARI */
+
+
+#if MACH == PMAC
+
+void pmac_init(void)
+{
+ struct device_node *node;
+
+ nvram_addrs = 0;
+ node = find_devices("nvram");
+ if (node == NULL) {
+ printk(KERN_ERR "Can't find NVRAM device.\n");
+ return;
+ }
+ nvram_addrs = node->n_addrs;
+ is_core_99 = device_is_compatible(node, "nvram,flash");
+ if (is_core_99) {
+ int i;
+
+ if (nvram_addrs < 1) {
+ printk(KERN_ERR "Bad number of addrs %d\n",
+ nvram_addrs);
+ return;
+ }
+ nvram_image = kmalloc(node->addrs[0].size, GFP_KERNEL);
+ if (!nvram_image) {
+ printk("KERN_ERR "nvram image kmalloc failed!\n");
+ return;
+ }
+ nvram_data = ioremap(node->addrs[0].address,
+ node->addrs[0].size);
+ for(i=0; i<node->addrs[0].size; i++) {
+ nvram_image[i] = in_8(nvram_data + i);
+ } else if (nvram_addrs == 1) {
+ nvram_data = ioremap(node->addrs[0].address,
+ node->addrs[0].size);
+ nvram_mult = (node->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
+ } else if (nvram_addrs == 2) {
+ nvram_addr = ioremap(node->addrs[0].address,
+ node->addrs[0].size);
+ nvram_data = ioremap(node->addrs[1].address,
+ node->addrs[1].size);
+ } else if (nvram_addrs == 0 && sys_ctrler == SYS_CTRLER_PMU)
+ nvram_naddrs = -1;
+ else
+ printk(KERN_ERR "Don't know how to access NVRAM with %d
+ addresses\n", nvram_naddrs);
+}
+
+
+unsigned char nvram_read_byte(int addr)
+{
+ struct adb_request req;
+
+ switch (nvram_naddrs) {
+#ifdef CONFIG_ADB_PMU
+ case -1:
+ if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
+ (addr >> 8) & 0xff, addr & 0xff))
+ break;
+ while(!req.complete)
+ pmu_poll();
+ return req.reply[1];;
+#endif
+ case 1:
+ if (is_core_99)
+ return nvram_image[addr];
+ return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult];
+ case 2:
+ *nvram_addr = addr >> 5;
+ eieio();
+ return nvram_data[(addr & 0x1f) << 4];
+ }
+ return 0;
+}
+
+void nvram_write_byte(unsigned char val, int addr)
+{
+ struct adb_request req;
+
+ switch(nvram_naddrs) {
+#ifdef CONFIG_ADB_PMU
+ case -1:
+ if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
+ (addr >> 8) & 0xff, addr & 0xff, val))
+ break;
+ while(!req.complete)
+ pmu_poll();
+ break;
+#endif
+ case 1:
+ if (is_core_99) {
+ nvram_image[addr] = val;
+ break;
+ }
+ nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult] = val;
+ break;
+ case 2:
+ *nvram_addr = addr >> 5;
+ eieio();
+ nvram_data[(addr & 0x1f) << 4] = val;
+ break;
+ }
+ eieio();
+}
+
+#endif /* MACH == PMAC */
+
+
/*
* The are the file operation function for user access to /dev/nvram
*/
@@ -414,6 +615,7 @@
if (!CHECK_DRIVER_INIT())
return( -ENXIO );
+ mach_init();
printk(KERN_INFO "Non-volatile memory driver v%s\n", NVRAM_VERSION );
misc_register( &nvram_dev );
create_proc_read_entry("driver/nvram",0,0,nvram_read_proc,NULL);
@@ -677,6 +879,64 @@
#endif
#endif /* MACH == ATARI */
+
+
+#if MACH == PMAC
+
+static int pmac_proc_infos( unsigned char *nvram, char *buffer, int *len,
+ off_t *begin, off_t offset, int size )
+{
+ int i, vi=0, off, len;
+ unsigned long bmask = 0x80000000;
+ char *p;
+
+ nv_buffer = (sruct nvbuf) &(nvram_image);
+
+ for (i=0; i<27; i++) {
+ switch(nv_vars[i].type) {
+ case boolean:
+ nv_vals[i].word_val = (nv_buffer.nv.bits & bmask) ? 1 : 0;
+ bmask >>= 1;
+ break;
+ case word;
+ nv_vals[i].word_val = nv_buffer.nv.vals[vi++];
+ break;
+ case string:
+ off = nv_buffer.nv.vals[vi] >> 16;
+ len = nv_buffer.nv.vals[vi++] & 0xffff;
+ nv_vals[i].str_val = nvstrbuf + nvstr_used;
+ memcpy(nv_vals[i].str_val, nv_buffer.c +
+ off - 0x1800, (size_t) len);
+ nv_vals[i].str_val[len] = (char) 0;
+ nvstr_used += len + 1;
+ break;
+ }
+ }
+
+ for (i=0; i<27; i++) {
+ switch(nv_vars[i].type) {
+ case boolean:
+ PRINT_PROC ( "%s - ", nv_vars[i].name);
+ PRINT_PROC ( "%s\n", nv_vals[i].word_val != 0 ?
+ "true" : "false");
+ break;
+ case word:
+ PRINT_PROC ( "%s - ", nv_vars[i].name);
+ PRINT_PROC ( "0x%lx\n", nv_vals[i].word_val);
+ break;
+ case string:
+ PRINT_PROC ( "%s - ", nv_vars[i].name);
+ PRINT_PROC ( "don't know about this yet\n" );
+ break;
+ }
+ }
+ return( 1 );
+}
+
+
+
+#endif /* MACH == PMAC */
+
/*
* Local variables:
More information about the Linuxppc-dev
mailing list