162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include "wakeup.h" 362306a36Sopenharmony_ci#include "boot.h" 462306a36Sopenharmony_ci 562306a36Sopenharmony_cistatic void udelay(int loops) 662306a36Sopenharmony_ci{ 762306a36Sopenharmony_ci while (loops--) 862306a36Sopenharmony_ci io_delay(); /* Approximately 1 us */ 962306a36Sopenharmony_ci} 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistatic void beep(unsigned int hz) 1262306a36Sopenharmony_ci{ 1362306a36Sopenharmony_ci u8 enable; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci if (!hz) { 1662306a36Sopenharmony_ci enable = 0x00; /* Turn off speaker */ 1762306a36Sopenharmony_ci } else { 1862306a36Sopenharmony_ci u16 div = 1193181/hz; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci outb(0xb6, 0x43); /* Ctr 2, squarewave, load, binary */ 2162306a36Sopenharmony_ci io_delay(); 2262306a36Sopenharmony_ci outb(div, 0x42); /* LSB of counter */ 2362306a36Sopenharmony_ci io_delay(); 2462306a36Sopenharmony_ci outb(div >> 8, 0x42); /* MSB of counter */ 2562306a36Sopenharmony_ci io_delay(); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci enable = 0x03; /* Turn on speaker */ 2862306a36Sopenharmony_ci } 2962306a36Sopenharmony_ci inb(0x61); /* Dummy read of System Control Port B */ 3062306a36Sopenharmony_ci io_delay(); 3162306a36Sopenharmony_ci outb(enable, 0x61); /* Enable timer 2 output to speaker */ 3262306a36Sopenharmony_ci io_delay(); 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define DOT_HZ 880 3662306a36Sopenharmony_ci#define DASH_HZ 587 3762306a36Sopenharmony_ci#define US_PER_DOT 125000 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* Okay, this is totally silly, but it's kind of fun. */ 4062306a36Sopenharmony_cistatic void send_morse(const char *pattern) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci char s; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci while ((s = *pattern++)) { 4562306a36Sopenharmony_ci switch (s) { 4662306a36Sopenharmony_ci case '.': 4762306a36Sopenharmony_ci beep(DOT_HZ); 4862306a36Sopenharmony_ci udelay(US_PER_DOT); 4962306a36Sopenharmony_ci beep(0); 5062306a36Sopenharmony_ci udelay(US_PER_DOT); 5162306a36Sopenharmony_ci break; 5262306a36Sopenharmony_ci case '-': 5362306a36Sopenharmony_ci beep(DASH_HZ); 5462306a36Sopenharmony_ci udelay(US_PER_DOT * 3); 5562306a36Sopenharmony_ci beep(0); 5662306a36Sopenharmony_ci udelay(US_PER_DOT); 5762306a36Sopenharmony_ci break; 5862306a36Sopenharmony_ci default: /* Assume it's a space */ 5962306a36Sopenharmony_ci udelay(US_PER_DOT * 3); 6062306a36Sopenharmony_ci break; 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistruct port_io_ops pio_ops; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_civoid main(void) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci init_default_io_ops(); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* Kill machine if structures are wrong */ 7262306a36Sopenharmony_ci if (wakeup_header.real_magic != 0x12345678) 7362306a36Sopenharmony_ci while (1) 7462306a36Sopenharmony_ci ; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (wakeup_header.realmode_flags & 4) 7762306a36Sopenharmony_ci send_morse("...-"); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (wakeup_header.realmode_flags & 1) 8062306a36Sopenharmony_ci asm volatile("lcallw $0xc000,$3"); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (wakeup_header.realmode_flags & 2) { 8362306a36Sopenharmony_ci /* Need to call BIOS */ 8462306a36Sopenharmony_ci probe_cards(0); 8562306a36Sopenharmony_ci set_mode(wakeup_header.video_mode); 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci} 88