1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include "wakeup.h" |
3 | #include "boot.h" |
4 | |
5 | static void udelay(int loops) |
6 | { |
7 | while (loops--) |
8 | io_delay(); /* Approximately 1 us */ |
9 | } |
10 | |
11 | static void beep(unsigned int hz) |
12 | { |
13 | u8 enable; |
14 | |
15 | if (!hz) { |
16 | enable = 0x00; /* Turn off speaker */ |
17 | } else { |
18 | u16 div = 1193181/hz; |
19 | |
20 | outb(0xb6, 0x43); /* Ctr 2, squarewave, load, binary */ |
21 | io_delay(); |
22 | outb(div, 0x42); /* LSB of counter */ |
23 | io_delay(); |
24 | outb(div >> 8, 0x42); /* MSB of counter */ |
25 | io_delay(); |
26 | |
27 | enable = 0x03; /* Turn on speaker */ |
28 | } |
29 | inb(0x61); /* Dummy read of System Control Port B */ |
30 | io_delay(); |
31 | outb(enable, 0x61); /* Enable timer 2 output to speaker */ |
32 | io_delay(); |
33 | } |
34 | |
35 | #define DOT_HZ 880 |
36 | #define DASH_HZ 587 |
37 | #define US_PER_DOT 125000 |
38 | |
39 | /* Okay, this is totally silly, but it's kind of fun. */ |
40 | static void send_morse(const char *pattern) |
41 | { |
42 | char s; |
43 | |
44 | while ((s = *pattern++)) { |
45 | switch (s) { |
46 | case '.': |
47 | beep(DOT_HZ); |
48 | udelay(US_PER_DOT); |
49 | beep(hz: 0); |
50 | udelay(US_PER_DOT); |
51 | break; |
52 | case '-': |
53 | beep(DASH_HZ); |
54 | udelay(US_PER_DOT * 3); |
55 | beep(hz: 0); |
56 | udelay(US_PER_DOT); |
57 | break; |
58 | default: /* Assume it's a space */ |
59 | udelay(US_PER_DOT * 3); |
60 | break; |
61 | } |
62 | } |
63 | } |
64 | |
65 | struct port_io_ops pio_ops; |
66 | |
67 | void main(void) |
68 | { |
69 | init_default_io_ops(); |
70 | |
71 | /* Kill machine if structures are wrong */ |
72 | if (wakeup_header.real_magic != 0x12345678) |
73 | while (1) |
74 | ; |
75 | |
76 | if (wakeup_header.realmode_flags & 4) |
77 | send_morse(pattern: "...-" ); |
78 | |
79 | if (wakeup_header.realmode_flags & 1) |
80 | asm volatile("lcallw $0xc000,$3" ); |
81 | |
82 | if (wakeup_header.realmode_flags & 2) { |
83 | /* Need to call BIOS */ |
84 | probe_cards(unsafe: 0); |
85 | set_mode(wakeup_header.video_mode); |
86 | } |
87 | } |
88 | |