Date: Thu, 20 Nov 1997 09:32:49 GMT
From: Roman Hodek <rnhodek@faui22c.informatik.uni-erlangen.de>
To: linux-m68k@lists.linux-m68k.org
Cc: <stepan@linux.de>
Subject: L68K: Probing of NVRAM size
Sender: owner-linux-m68k@phil.uni-sb.de


Is is Stefan Reinauer's patch again, with some little cleanups by me
and in a readble format now :-)

Roman

------------------------------------------------------------------------------
--- linux-2.1.64/drivers/char/nvram.c~	Thu Nov 13 15:20:28 1997
+++ linux-2.1.64/drivers/char/nvram.c	Thu Nov 20 10:28:30 1997
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 1997 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
  * idea by and with help from Richard Jelinek <rj@suse.de>
+ * Autoprobing for NVRAM size by Stefan Reinauer <stepan@linux.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
@@ -10,7 +11,8 @@
  * "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
+ * size of this file is 50 on Ataris and old PCs, 114 bytes on newer PCs.
+ * That4s 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
@@ -27,7 +29,7 @@
  *
  */
 
-#define NVRAM_VERSION		"1.0"
+#define NVRAM_VERSION		"1.1"
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -106,15 +108,17 @@
 
 static int nvram_open_cnt = 0;	/* #times opened */
 static int nvram_open_mode;		/* special open modes */
+static unsigned nvram_bytes;	/* number of NVRAM bytes */
 #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			50	/* number of NVRAM bytes */
 
 
 static int mach_check_checksum( void );
 static void mach_set_checksum( void );
+static int nvram_probe( 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 );
@@ -221,7 +225,7 @@
 		offset += file->f_pos;
 		break;
 	  case 2:
-		offset += NVRAM_BYTES;
+		offset += nvram_bytes;
 		break;
 	}
 	return( (offset >= 0) ? (file->f_pos = offset) : -EINVAL );
@@ -242,7 +246,7 @@
 		return( -EIO );
 	}
 
-	for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp )
+	for( ; count-- > 0 && i < nvram_bytes; ++i, ++tmp )
 		put_user( nvram_read_int(i), tmp );
 	*ppos = i;
 
@@ -266,7 +270,7 @@
 		return( -EIO );
 	}
 
-	for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp ) {
+	for( ; count-- > 0 && i < nvram_bytes; ++i, ++tmp ) {
 		get_user( c, tmp );
 		nvram_write_int( c, i );
 	}
@@ -292,7 +296,7 @@
 		save_flags(flags);
 		cli();
 
-		for( i = 0; i < NVRAM_BYTES; ++i )
+		for( i = 0; i < nvram_bytes; ++i )
 			nvram_write_int( 0, i );
 		nvram_set_checksum_int();
 		
@@ -353,13 +357,13 @@
 							int size, int *eof, void *data )
 {
 	unsigned long flags;
-	unsigned char contents[NVRAM_BYTES];
+	unsigned char contents[nvram_bytes];
     int i, len = 0;
     off_t begin = 0;
 	
 	save_flags(flags);
 	cli();
-	for( i = 0; i < NVRAM_BYTES; ++i )
+	for( i = 0; i < nvram_bytes; ++i )
 		contents[i] = nvram_read_int( i );
 	restore_flags(flags);
 	
@@ -414,6 +418,8 @@
 
 	printk(KERN_INFO "Non-volatile memory driver v%s\n", NVRAM_VERSION );
 	misc_register( &nvram_dev );
+	nvram_bytes = nvram_probe() - RTC_FIRST_BYTE;
+
 #ifdef CONFIG_PROC_FS
 	if ((proc_nvram = create_proc_entry( "nvram", 0, 0 )))
 		proc_nvram->read_proc = nvram_read_proc;
@@ -495,7 +501,7 @@
 	restore_flags(flags);
 	
 	PRINT_PROC( "Checksum status: %svalid\n", checksum ? "" : "not " );
-
+	PRINT_PROC( "NV-RAM size    : %d bytes\n", nvram_bytes+RTC_FIRST_BYTE );
 	PRINT_PROC( "# floppies     : %d\n",
 				(nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0 );
 	PRINT_PROC( "Floppy 0 type  : " );
@@ -686,6 +692,22 @@
 #endif
 
 #endif /* MACH == ATARI */
+
+static int nvram_probe()
+{
+  int size=64, i;
+
+  printk("Probing nvram size... ");
+  for (i=RTC_FIRST_BYTE;i<size;i++)
+    if (CMOS_READ(i) != CMOS_READ(i+size)) {
+      size+=size;
+      i=RTC_FIRST_BYTE-1;
+    }
+
+  printk(" found %d bytes\n", size);
+  return (size);
+}
+
 
 /*
  * Local variables:
