1 // SPDX-License-Identifier: GPL-2.0 2 #include "wakeup.h" 3 #include "boot.h" 4 5 static void udelay(int loops) 6 { 7 while (loops--) 8 io_delay(); /* Approximately 1 us */ 9 } 10 11 static 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. */ 40 static 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 65 void 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