// SPDX-License-Identifier: GPL-2.0 
 | 
#include "wakeup.h" 
 | 
#include "boot.h" 
 | 
  
 | 
static void udelay(int loops) 
 | 
{ 
 | 
    while (loops--) 
 | 
        io_delay();    /* Approximately 1 us */ 
 | 
} 
 | 
  
 | 
static void beep(unsigned int hz) 
 | 
{ 
 | 
    u8 enable; 
 | 
  
 | 
    if (!hz) { 
 | 
        enable = 0x00;        /* Turn off speaker */ 
 | 
    } else { 
 | 
        u16 div = 1193181/hz; 
 | 
  
 | 
        outb(0xb6, 0x43);    /* Ctr 2, squarewave, load, binary */ 
 | 
        io_delay(); 
 | 
        outb(div, 0x42);    /* LSB of counter */ 
 | 
        io_delay(); 
 | 
        outb(div >> 8, 0x42);    /* MSB of counter */ 
 | 
        io_delay(); 
 | 
  
 | 
        enable = 0x03;        /* Turn on speaker */ 
 | 
    } 
 | 
    inb(0x61);        /* Dummy read of System Control Port B */ 
 | 
    io_delay(); 
 | 
    outb(enable, 0x61);    /* Enable timer 2 output to speaker */ 
 | 
    io_delay(); 
 | 
} 
 | 
  
 | 
#define DOT_HZ        880 
 | 
#define DASH_HZ        587 
 | 
#define US_PER_DOT    125000 
 | 
  
 | 
/* Okay, this is totally silly, but it's kind of fun. */ 
 | 
static void send_morse(const char *pattern) 
 | 
{ 
 | 
    char s; 
 | 
  
 | 
    while ((s = *pattern++)) { 
 | 
        switch (s) { 
 | 
        case '.': 
 | 
            beep(DOT_HZ); 
 | 
            udelay(US_PER_DOT); 
 | 
            beep(0); 
 | 
            udelay(US_PER_DOT); 
 | 
            break; 
 | 
        case '-': 
 | 
            beep(DASH_HZ); 
 | 
            udelay(US_PER_DOT * 3); 
 | 
            beep(0); 
 | 
            udelay(US_PER_DOT); 
 | 
            break; 
 | 
        default:    /* Assume it's a space */ 
 | 
            udelay(US_PER_DOT * 3); 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
} 
 | 
  
 | 
void main(void) 
 | 
{ 
 | 
    /* Kill machine if structures are wrong */ 
 | 
    if (wakeup_header.real_magic != 0x12345678) 
 | 
        while (1) 
 | 
            ; 
 | 
  
 | 
    if (wakeup_header.realmode_flags & 4) 
 | 
        send_morse("...-"); 
 | 
  
 | 
    if (wakeup_header.realmode_flags & 1) 
 | 
        asm volatile("lcallw   $0xc000,$3"); 
 | 
  
 | 
    if (wakeup_header.realmode_flags & 2) { 
 | 
        /* Need to call BIOS */ 
 | 
        probe_cards(0); 
 | 
        set_mode(wakeup_header.video_mode); 
 | 
    } 
 | 
} 
 |