Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / libc / stdio / delay.c
blob7ce01ff1d5a49d7a5b6df74da653d50f7e62a61d
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
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 3 of the License, or
8 * (at your option) any later version.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * Allright, let's review how we're going to do this.
23 * Goal:
24 * The goal is to create a reasonably accurate version of the delay()
25 * function, which creates a delay in multiples of one millisecond.
27 * Restrictions:
28 * We don't want to use the PIT for the delay. In your average
29 * bare-hardware system (ie OS) you'll be using the PIT for quite a few
30 * other things already (in my OS code, channel 0 and 1 are used by the
31 * scheduler, and channel 2 would probably be needed to control the
32 * speaker.)
34 * Method:
35 * A simple loop would delay the computer wonderfully. Ie, take something
36 * like:
38 * for(i=0;i<BIGNUMBER;i++); // Delay loop
40 * That kills time wonderfully. All we need to do is to find out what
41 * BIGNUMBER we need to use to delay one millisecond. Finding the correct
42 * BIGNUMBER for your machine is called *delay loop calibration*.
44 * We can calibrate the delay loop using the PIT. In the initialisation
45 * phase of the OS, when the PIT is not yet hooked to the scheduler, it
46 * can be freely used to do this. When the delay loop has been calibrated
47 * against the PIT, the PIT is free to be used for other purposes.
49 * There are many ways to calibrate a delay loop with the PIT. This is
50 * one way (used in Linux.) More documentation in the code.
53 /**************************************************************************/
56 * The delay function:
57 * Have a look at this function before you look at the calibration code.
58 * Basically, delay_count is the number you have to count to in order to
59 * kill 1ms. delay() takes the amount of milliseconds to delay as
60 * parameter.
62 * The goal of the rest of this code is to determine what delay_count *is*
63 * for your machine.
65 * Keep delay_count initialised to 1. We'll need that later.
68 static unsigned long delay_count = 1;
71 * When I was testing the delay code, I notice that the calibration we use
72 * is very delicate. Originally, I had inlined the delay for() loops into
73 * the delay() and calibrateDelayLoop() functions, but this doesn't work.
74 * Due to different register allocation or something similar the compiler
75 * might have generated different code in the two situations (I didn't
76 * check this.) Or alignment differences might have caused the problems.
77 * Anyway, to solve the problem, we always use the __delay() function for
78 * the delay for() loop, because it always is the same code with the same
79 * alignment. __delay() is called from delay() as well as from
80 * calibrateDelayLoop(). By using __delay() we can fine-tune our
81 * calibration without it losing its finesse afterwards.
84 void __delay (unsigned loops)
86 unsigned long c;
88 for (c = 0; c < (unsigned) loops; c ++);
91 void delay(unsigned long milliseconds)
93 __delay (milliseconds * delay_count); /* Delay milliseconds ms */
96 /* The end */