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