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