Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/realmode/rm/wakemain.c
26490 views
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(0);
50
udelay(US_PER_DOT);
51
break;
52
case '-':
53
beep(DASH_HZ);
54
udelay(US_PER_DOT * 3);
55
beep(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("...-");
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(0);
85
set_mode(wakeup_header.video_mode);
86
}
87
}
88
89