90da33db91c83c320d47e2883dd85f8c337f2b84
[reactos.git] / boot / freeldr / freeldr / arch / i386 / i386rtl.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <freeldr.h>
21
22 void sound(int freq);
23 void delay(unsigned msec);
24
25 VOID PcBeep(VOID)
26 {
27 sound(700);
28 delay(200);
29 sound(0);
30 }
31
32 void delay(unsigned msec)
33 {
34 REGS Regs;
35 unsigned usec;
36 unsigned msec_this;
37
38 // Int 15h AH=86h
39 // BIOS - WAIT (AT,PS)
40 //
41 // AH = 86h
42 // CX:DX = interval in microseconds
43 // Return:
44 // CF clear if successful (wait interval elapsed)
45 // CF set on error or AH=83h wait already in progress
46 // AH = status (see #00496)
47
48 // Note: The resolution of the wait period is 977 microseconds on
49 // many systems because many BIOSes use the 1/1024 second fast
50 // interrupt from the AT real-time clock chip which is available on INT 70;
51 // because newer BIOSes may have much more precise timers available, it is
52 // not possible to use this function accurately for very short delays unless
53 // the precise behavior of the BIOS is known (or found through testing)
54
55 while (msec)
56 {
57 msec_this = msec;
58
59 if (msec_this > 4000)
60 {
61 msec_this = 4000;
62 }
63
64 usec = msec_this * 1000;
65
66 Regs.b.ah = 0x86;
67 Regs.w.cx = usec >> 16;
68 Regs.w.dx = usec & 0xffff;
69 Int386(0x15, &Regs, &Regs);
70
71 msec -= msec_this;
72 }
73 }
74
75 void sound(int freq)
76 {
77 int scale;
78
79 if (freq == 0)
80 {
81 WRITE_PORT_UCHAR((PUCHAR)0x61, READ_PORT_UCHAR((PUCHAR)0x61) & ~3);
82 return;
83 }
84
85 scale = 1193046 / freq;
86 WRITE_PORT_UCHAR((PUCHAR)0x43, 0xb6);
87 WRITE_PORT_UCHAR((PUCHAR)0x42, scale & 0xff);
88 WRITE_PORT_UCHAR((PUCHAR)0x42, scale >> 8);
89 WRITE_PORT_UCHAR((PUCHAR)0x61, READ_PORT_UCHAR((PUCHAR)0x61) | 3);
90 }