root/arch/m68k/atari/nvram.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __nvram_read_byte
  2. __nvram_write_byte
  3. __nvram_check_checksum
  4. __nvram_set_checksum
  5. atari_nvram_set_checksum
  6. atari_nvram_initialize
  7. atari_nvram_read
  8. atari_nvram_write
  9. atari_nvram_get_size
  10. atari_nvram_proc_read
  11. nvram_proc_read
  12. atari_nvram_init

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * CMOS/NV-RAM driver for Atari. Adapted from drivers/char/nvram.c.
   4  * Copyright (C) 1997 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
   5  * idea by and with help from Richard Jelinek <rj@suse.de>
   6  * Portions copyright (c) 2001,2002 Sun Microsystems (thockin@sun.com)
   7  * Further contributions from Cesar Barros, Erik Gilling, Tim Hockin and
   8  * Wim Van Sebroeck.
   9  */
  10 
  11 #include <linux/errno.h>
  12 #include <linux/init.h>
  13 #include <linux/mc146818rtc.h>
  14 #include <linux/module.h>
  15 #include <linux/nvram.h>
  16 #include <linux/proc_fs.h>
  17 #include <linux/seq_file.h>
  18 #include <linux/spinlock.h>
  19 #include <linux/types.h>
  20 #include <asm/atarihw.h>
  21 #include <asm/atariints.h>
  22 
  23 #define NVRAM_BYTES             50
  24 
  25 /* It is worth noting that these functions all access bytes of general
  26  * purpose memory in the NVRAM - that is to say, they all add the
  27  * NVRAM_FIRST_BYTE offset. Pass them offsets into NVRAM as if you did not
  28  * know about the RTC cruft.
  29  */
  30 
  31 /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
  32  * rtc_lock held. Due to the index-port/data-port design of the RTC, we
  33  * don't want two different things trying to get to it at once. (e.g. the
  34  * periodic 11 min sync from kernel/time/ntp.c vs. this driver.)
  35  */
  36 
  37 static unsigned char __nvram_read_byte(int i)
  38 {
  39         return CMOS_READ(NVRAM_FIRST_BYTE + i);
  40 }
  41 
  42 /* This races nicely with trying to read with checksum checking */
  43 static void __nvram_write_byte(unsigned char c, int i)
  44 {
  45         CMOS_WRITE(c, NVRAM_FIRST_BYTE + i);
  46 }
  47 
  48 /* On Ataris, the checksum is over all bytes except the checksum bytes
  49  * themselves; these are at the very end.
  50  */
  51 #define ATARI_CKS_RANGE_START   0
  52 #define ATARI_CKS_RANGE_END     47
  53 #define ATARI_CKS_LOC           48
  54 
  55 static int __nvram_check_checksum(void)
  56 {
  57         int i;
  58         unsigned char sum = 0;
  59 
  60         for (i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i)
  61                 sum += __nvram_read_byte(i);
  62         return (__nvram_read_byte(ATARI_CKS_LOC) == (~sum & 0xff)) &&
  63                (__nvram_read_byte(ATARI_CKS_LOC + 1) == (sum & 0xff));
  64 }
  65 
  66 static void __nvram_set_checksum(void)
  67 {
  68         int i;
  69         unsigned char sum = 0;
  70 
  71         for (i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i)
  72                 sum += __nvram_read_byte(i);
  73         __nvram_write_byte(~sum, ATARI_CKS_LOC);
  74         __nvram_write_byte(sum, ATARI_CKS_LOC + 1);
  75 }
  76 
  77 long atari_nvram_set_checksum(void)
  78 {
  79         spin_lock_irq(&rtc_lock);
  80         __nvram_set_checksum();
  81         spin_unlock_irq(&rtc_lock);
  82         return 0;
  83 }
  84 
  85 long atari_nvram_initialize(void)
  86 {
  87         loff_t i;
  88 
  89         spin_lock_irq(&rtc_lock);
  90         for (i = 0; i < NVRAM_BYTES; ++i)
  91                 __nvram_write_byte(0, i);
  92         __nvram_set_checksum();
  93         spin_unlock_irq(&rtc_lock);
  94         return 0;
  95 }
  96 
  97 ssize_t atari_nvram_read(char *buf, size_t count, loff_t *ppos)
  98 {
  99         char *p = buf;
 100         loff_t i;
 101 
 102         spin_lock_irq(&rtc_lock);
 103         if (!__nvram_check_checksum()) {
 104                 spin_unlock_irq(&rtc_lock);
 105                 return -EIO;
 106         }
 107         for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p)
 108                 *p = __nvram_read_byte(i);
 109         spin_unlock_irq(&rtc_lock);
 110 
 111         *ppos = i;
 112         return p - buf;
 113 }
 114 
 115 ssize_t atari_nvram_write(char *buf, size_t count, loff_t *ppos)
 116 {
 117         char *p = buf;
 118         loff_t i;
 119 
 120         spin_lock_irq(&rtc_lock);
 121         if (!__nvram_check_checksum()) {
 122                 spin_unlock_irq(&rtc_lock);
 123                 return -EIO;
 124         }
 125         for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p)
 126                 __nvram_write_byte(*p, i);
 127         __nvram_set_checksum();
 128         spin_unlock_irq(&rtc_lock);
 129 
 130         *ppos = i;
 131         return p - buf;
 132 }
 133 
 134 ssize_t atari_nvram_get_size(void)
 135 {
 136         return NVRAM_BYTES;
 137 }
 138 
 139 #ifdef CONFIG_PROC_FS
 140 static struct {
 141         unsigned char val;
 142         const char *name;
 143 } boot_prefs[] = {
 144         { 0x80, "TOS" },
 145         { 0x40, "ASV" },
 146         { 0x20, "NetBSD (?)" },
 147         { 0x10, "Linux" },
 148         { 0x00, "unspecified" },
 149 };
 150 
 151 static const char * const languages[] = {
 152         "English (US)",
 153         "German",
 154         "French",
 155         "English (UK)",
 156         "Spanish",
 157         "Italian",
 158         "6 (undefined)",
 159         "Swiss (French)",
 160         "Swiss (German)",
 161 };
 162 
 163 static const char * const dateformat[] = {
 164         "MM%cDD%cYY",
 165         "DD%cMM%cYY",
 166         "YY%cMM%cDD",
 167         "YY%cDD%cMM",
 168         "4 (undefined)",
 169         "5 (undefined)",
 170         "6 (undefined)",
 171         "7 (undefined)",
 172 };
 173 
 174 static const char * const colors[] = {
 175         "2", "4", "16", "256", "65536", "??", "??", "??"
 176 };
 177 
 178 static void atari_nvram_proc_read(unsigned char *nvram, struct seq_file *seq,
 179                                   void *offset)
 180 {
 181         int checksum;
 182         int i;
 183         unsigned int vmode;
 184 
 185         spin_lock_irq(&rtc_lock);
 186         checksum = __nvram_check_checksum();
 187         spin_unlock_irq(&rtc_lock);
 188 
 189         seq_printf(seq, "Checksum status  : %svalid\n", checksum ? "" : "not ");
 190 
 191         seq_puts(seq, "Boot preference  : ");
 192         for (i = ARRAY_SIZE(boot_prefs) - 1; i >= 0; --i)
 193                 if (nvram[1] == boot_prefs[i].val) {
 194                         seq_printf(seq, "%s\n", boot_prefs[i].name);
 195                         break;
 196                 }
 197         if (i < 0)
 198                 seq_printf(seq, "0x%02x (undefined)\n", nvram[1]);
 199 
 200         seq_printf(seq, "SCSI arbitration : %s\n",
 201                    (nvram[16] & 0x80) ? "on" : "off");
 202         seq_puts(seq, "SCSI host ID     : ");
 203         if (nvram[16] & 0x80)
 204                 seq_printf(seq, "%d\n", nvram[16] & 7);
 205         else
 206                 seq_puts(seq, "n/a\n");
 207 
 208         if (!MACH_IS_FALCON)
 209                 return;
 210 
 211         seq_puts(seq, "OS language      : ");
 212         if (nvram[6] < ARRAY_SIZE(languages))
 213                 seq_printf(seq, "%s\n", languages[nvram[6]]);
 214         else
 215                 seq_printf(seq, "%u (undefined)\n", nvram[6]);
 216         seq_puts(seq, "Keyboard language: ");
 217         if (nvram[7] < ARRAY_SIZE(languages))
 218                 seq_printf(seq, "%s\n", languages[nvram[7]]);
 219         else
 220                 seq_printf(seq, "%u (undefined)\n", nvram[7]);
 221         seq_puts(seq, "Date format      : ");
 222         seq_printf(seq, dateformat[nvram[8] & 7],
 223                    nvram[9] ? nvram[9] : '/', nvram[9] ? nvram[9] : '/');
 224         seq_printf(seq, ", %dh clock\n", nvram[8] & 16 ? 24 : 12);
 225         seq_puts(seq, "Boot delay       : ");
 226         if (nvram[10] == 0)
 227                 seq_puts(seq, "default\n");
 228         else
 229                 seq_printf(seq, "%ds%s\n", nvram[10],
 230                            nvram[10] < 8 ? ", no memory test" : "");
 231 
 232         vmode = (nvram[14] << 8) | nvram[15];
 233         seq_printf(seq,
 234                    "Video mode       : %s colors, %d columns, %s %s monitor\n",
 235                    colors[vmode & 7], vmode & 8 ? 80 : 40,
 236                    vmode & 16 ? "VGA" : "TV", vmode & 32 ? "PAL" : "NTSC");
 237         seq_printf(seq,
 238                    "                   %soverscan, compat. mode %s%s\n",
 239                    vmode & 64 ? "" : "no ", vmode & 128 ? "on" : "off",
 240                    vmode & 256 ?
 241                    (vmode & 16 ? ", line doubling" : ", half screen") : "");
 242 }
 243 
 244 static int nvram_proc_read(struct seq_file *seq, void *offset)
 245 {
 246         unsigned char contents[NVRAM_BYTES];
 247         int i;
 248 
 249         spin_lock_irq(&rtc_lock);
 250         for (i = 0; i < NVRAM_BYTES; ++i)
 251                 contents[i] = __nvram_read_byte(i);
 252         spin_unlock_irq(&rtc_lock);
 253 
 254         atari_nvram_proc_read(contents, seq, offset);
 255 
 256         return 0;
 257 }
 258 
 259 static int __init atari_nvram_init(void)
 260 {
 261         if (!(MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK)))
 262                 return -ENODEV;
 263 
 264         if (!proc_create_single("driver/nvram", 0, NULL, nvram_proc_read)) {
 265                 pr_err("nvram: can't create /proc/driver/nvram\n");
 266                 return -ENOMEM;
 267         }
 268 
 269         return 0;
 270 }
 271 device_initcall(atari_nvram_init);
 272 #endif /* CONFIG_PROC_FS */

/* [<][>][^][v][top][bottom][index][help] */