linux/arch/x86/realmode/rm/wakemain.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include "wakeup.h"
   3#include "boot.h"
   4
   5static void udelay(int loops)
   6{
   7        while (loops--)
   8                io_delay();     /* Approximately 1 us */
   9}
  10
  11static 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. */
  40static 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
  65void main(void)
  66{
  67        /* Kill machine if structures are wrong */
  68        if (wakeup_header.real_magic != 0x12345678)
  69                while (1)
  70                        ;
  71
  72        if (wakeup_header.realmode_flags & 4)
  73                send_morse("...-");
  74
  75        if (wakeup_header.realmode_flags & 1)
  76                asm volatile("lcallw   $0xc000,$3");
  77
  78        if (wakeup_header.realmode_flags & 2) {
  79                /* Need to call BIOS */
  80                probe_cards(0);
  81                set_mode(wakeup_header.video_mode);
  82        }
  83}
  84