xref: /OK3568_Linux_fs/kernel/arch/x86/realmode/rm/wakemain.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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