| 1 | |
| 2 | |
| 3 | * Implement 'Simple Boot Flag Specification 2.0'
|
| 4 |
|
| 5 | #include <linux/types.h>
|
| 6 | #include <linux/kernel.h>
|
| 7 | #include <linux/init.h>
|
| 8 | #include <linux/string.h>
|
| 9 | #include <linux/spinlock.h>
|
| 10 | #include <linux/acpi.h>
|
| 11 | #include <linux/bitops.h>
|
| 12 | #include <asm/io.h>
|
| 13 |
|
| 14 | #include <linux/mc146818rtc.h>
|
| 15 |
|
| 16 | #define SBF_RESERVED (0x78)
|
| 17 | #define SBF_PNPOS (1<<0)
|
| 18 | #define SBF_BOOTING (1<<1)
|
| 19 | #define SBF_DIAG (1<<2)
|
| 20 | #define SBF_PARITY (1<<7)
|
| 21 |
|
| 22 | int sbf_port __initdata = -1;
|
| 23 |
|
| 24 | static void __init sbf_write(u8 v)
|
| 25 | {
|
| 26 | unsigned long flags;
|
| 27 |
|
| 28 | if (sbf_port != -1) {
|
| 29 | if (!parity8(v))
|
| 30 | v ^= SBF_PARITY;
|
| 31 |
|
| 32 | printk(KERN_INFO "Simple Boot Flag at 0x%x set to 0x%x\n",
|
| 33 | sbf_port, v);
|
| 34 |
|
| 35 | spin_lock_irqsave(&rtc_lock, flags);
|
| 36 | CMOS_WRITE(v, sbf_port);
|
| 37 | spin_unlock_irqrestore(&rtc_lock, flags);
|
| 38 | }
|
| 39 | }
|
| 40 |
|
| 41 | static u8 __init sbf_read(void)
|
| 42 | {
|
| 43 | unsigned long flags;
|
| 44 | u8 v;
|
| 45 |
|
| 46 | if (sbf_port == -1)
|
| 47 | return 0;
|
| 48 |
|
| 49 | spin_lock_irqsave(&rtc_lock, flags);
|
| 50 | v = CMOS_READ(sbf_port);
|
| 51 | spin_unlock_irqrestore(&rtc_lock, flags);
|
| 52 |
|
| 53 | return v;
|
| 54 | }
|
| 55 |
|
| 56 | static bool __init sbf_value_valid(u8 v)
|
| 57 | {
|
| 58 | if (v & SBF_RESERVED)
|
| 59 | return false;
|
| 60 | if (!parity8(v))
|
| 61 | return false;
|
| 62 |
|
| 63 | return true;
|
| 64 | }
|
| 65 |
|
| 66 | static int __init sbf_init(void)
|
| 67 | {
|
| 68 | u8 v;
|
| 69 |
|
| 70 | if (sbf_port == -1)
|
| 71 | return 0;
|
| 72 |
|
| 73 | v = sbf_read();
|
| 74 | if (!sbf_value_valid(v)) {
|
| 75 | printk(KERN_WARNING "Simple Boot Flag value 0x%x read from "
|
| 76 | "CMOS RAM was invalid\n", v);
|
| 77 | }
|
| 78 |
|
| 79 | v &= ~SBF_RESERVED;
|
| 80 | v &= ~SBF_BOOTING;
|
| 81 | v &= ~SBF_DIAG;
|
| 82 | #if defined(CONFIG_ISAPNP)
|
| 83 | v |= SBF_PNPOS;
|
| 84 | #endif
|
| 85 | sbf_write(v);
|
| 86 |
|
| 87 | return 0;
|
| 88 | }
|
| 89 | arch_initcall(sbf_init);
|