xref: /openbmc/linux/arch/x86/realmode/rm/wakemain.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1  // SPDX-License-Identifier: GPL-2.0
2  #include "wakeup.h"
3  #include "boot.h"
4  
udelay(int loops)5  static void udelay(int loops)
6  {
7  	while (loops--)
8  		io_delay();	/* Approximately 1 us */
9  }
10  
beep(unsigned int hz)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. */
send_morse(const char * pattern)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  
main(void)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