0001
0002
0003
0004
0005 #include <linux/types.h>
0006 #include <linux/kernel.h>
0007 #include <linux/init.h>
0008 #include <linux/string.h>
0009 #include <linux/spinlock.h>
0010 #include <linux/acpi.h>
0011 #include <asm/io.h>
0012
0013 #include <linux/mc146818rtc.h>
0014
0015 #define SBF_RESERVED (0x78)
0016 #define SBF_PNPOS (1<<0)
0017 #define SBF_BOOTING (1<<1)
0018 #define SBF_DIAG (1<<2)
0019 #define SBF_PARITY (1<<7)
0020
0021 int sbf_port __initdata = -1;
0022
0023 static int __init parity(u8 v)
0024 {
0025 int x = 0;
0026 int i;
0027
0028 for (i = 0; i < 8; i++) {
0029 x ^= (v & 1);
0030 v >>= 1;
0031 }
0032
0033 return x;
0034 }
0035
0036 static void __init sbf_write(u8 v)
0037 {
0038 unsigned long flags;
0039
0040 if (sbf_port != -1) {
0041 v &= ~SBF_PARITY;
0042 if (!parity(v))
0043 v |= SBF_PARITY;
0044
0045 printk(KERN_INFO "Simple Boot Flag at 0x%x set to 0x%x\n",
0046 sbf_port, v);
0047
0048 spin_lock_irqsave(&rtc_lock, flags);
0049 CMOS_WRITE(v, sbf_port);
0050 spin_unlock_irqrestore(&rtc_lock, flags);
0051 }
0052 }
0053
0054 static u8 __init sbf_read(void)
0055 {
0056 unsigned long flags;
0057 u8 v;
0058
0059 if (sbf_port == -1)
0060 return 0;
0061
0062 spin_lock_irqsave(&rtc_lock, flags);
0063 v = CMOS_READ(sbf_port);
0064 spin_unlock_irqrestore(&rtc_lock, flags);
0065
0066 return v;
0067 }
0068
0069 static int __init sbf_value_valid(u8 v)
0070 {
0071 if (v & SBF_RESERVED)
0072 return 0;
0073 if (!parity(v))
0074 return 0;
0075
0076 return 1;
0077 }
0078
0079 static int __init sbf_init(void)
0080 {
0081 u8 v;
0082
0083 if (sbf_port == -1)
0084 return 0;
0085
0086 v = sbf_read();
0087 if (!sbf_value_valid(v)) {
0088 printk(KERN_WARNING "Simple Boot Flag value 0x%x read from "
0089 "CMOS RAM was invalid\n", v);
0090 }
0091
0092 v &= ~SBF_RESERVED;
0093 v &= ~SBF_BOOTING;
0094 v &= ~SBF_DIAG;
0095 #if defined(CONFIG_ISAPNP)
0096 v |= SBF_PNPOS;
0097 #endif
0098 sbf_write(v);
0099
0100 return 0;
0101 }
0102 arch_initcall(sbf_init);