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 struct port_io_ops pio_ops; 66 67 void main(void) 68 { 69 init_default_io_ops(); 70 71 /* Kill machine if structures are wrong */ 72 if (wakeup_header.real_magic != 0x12345678) 73 while (1) 74 ; 75 76 if (wakeup_header.realmode_flags & 4) 77 send_morse("...-"); 78 79 if (wakeup_header.realmode_flags & 1) 80 asm volatile("lcallw $0xc000,$3"); 81 82 if (wakeup_header.realmode_flags & 2) { 83 /* Need to call BIOS */ 84 probe_cards(0); 85 set_mode(wakeup_header.video_mode); 86 } 87 } 88