18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include "wakeup.h" 38c2ecf20Sopenharmony_ci#include "boot.h" 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_cistatic void udelay(int loops) 68c2ecf20Sopenharmony_ci{ 78c2ecf20Sopenharmony_ci while (loops--) 88c2ecf20Sopenharmony_ci io_delay(); /* Approximately 1 us */ 98c2ecf20Sopenharmony_ci} 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistatic void beep(unsigned int hz) 128c2ecf20Sopenharmony_ci{ 138c2ecf20Sopenharmony_ci u8 enable; 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci if (!hz) { 168c2ecf20Sopenharmony_ci enable = 0x00; /* Turn off speaker */ 178c2ecf20Sopenharmony_ci } else { 188c2ecf20Sopenharmony_ci u16 div = 1193181/hz; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci outb(0xb6, 0x43); /* Ctr 2, squarewave, load, binary */ 218c2ecf20Sopenharmony_ci io_delay(); 228c2ecf20Sopenharmony_ci outb(div, 0x42); /* LSB of counter */ 238c2ecf20Sopenharmony_ci io_delay(); 248c2ecf20Sopenharmony_ci outb(div >> 8, 0x42); /* MSB of counter */ 258c2ecf20Sopenharmony_ci io_delay(); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci enable = 0x03; /* Turn on speaker */ 288c2ecf20Sopenharmony_ci } 298c2ecf20Sopenharmony_ci inb(0x61); /* Dummy read of System Control Port B */ 308c2ecf20Sopenharmony_ci io_delay(); 318c2ecf20Sopenharmony_ci outb(enable, 0x61); /* Enable timer 2 output to speaker */ 328c2ecf20Sopenharmony_ci io_delay(); 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define DOT_HZ 880 368c2ecf20Sopenharmony_ci#define DASH_HZ 587 378c2ecf20Sopenharmony_ci#define US_PER_DOT 125000 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* Okay, this is totally silly, but it's kind of fun. */ 408c2ecf20Sopenharmony_cistatic void send_morse(const char *pattern) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci char s; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci while ((s = *pattern++)) { 458c2ecf20Sopenharmony_ci switch (s) { 468c2ecf20Sopenharmony_ci case '.': 478c2ecf20Sopenharmony_ci beep(DOT_HZ); 488c2ecf20Sopenharmony_ci udelay(US_PER_DOT); 498c2ecf20Sopenharmony_ci beep(0); 508c2ecf20Sopenharmony_ci udelay(US_PER_DOT); 518c2ecf20Sopenharmony_ci break; 528c2ecf20Sopenharmony_ci case '-': 538c2ecf20Sopenharmony_ci beep(DASH_HZ); 548c2ecf20Sopenharmony_ci udelay(US_PER_DOT * 3); 558c2ecf20Sopenharmony_ci beep(0); 568c2ecf20Sopenharmony_ci udelay(US_PER_DOT); 578c2ecf20Sopenharmony_ci break; 588c2ecf20Sopenharmony_ci default: /* Assume it's a space */ 598c2ecf20Sopenharmony_ci udelay(US_PER_DOT * 3); 608c2ecf20Sopenharmony_ci break; 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_civoid main(void) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci /* Kill machine if structures are wrong */ 688c2ecf20Sopenharmony_ci if (wakeup_header.real_magic != 0x12345678) 698c2ecf20Sopenharmony_ci while (1) 708c2ecf20Sopenharmony_ci ; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (wakeup_header.realmode_flags & 4) 738c2ecf20Sopenharmony_ci send_morse("...-"); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci if (wakeup_header.realmode_flags & 1) 768c2ecf20Sopenharmony_ci asm volatile("lcallw $0xc000,$3"); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (wakeup_header.realmode_flags & 2) { 798c2ecf20Sopenharmony_ci /* Need to call BIOS */ 808c2ecf20Sopenharmony_ci probe_cards(0); 818c2ecf20Sopenharmony_ci set_mode(wakeup_header.video_mode); 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci} 84