The one-shot pit delay was not calibrated properly.
This fixes the pit_udelay() function so it can be used for
tiny delays within the kernel. Removes dependence on HPET for smp.
---
i386/i386/pit.c | 16 ++++++++++------
i386/i386/pit.h | 3 +++
i386/i386/smp.c | 5 +++--
3 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/i386/i386/pit.c b/i386/i386/pit.c
index 6c006a98..1863e283 100644
--- a/i386/i386/pit.c
+++ b/i386/i386/pit.c
@@ -66,10 +66,10 @@ int pit0_mode = PIT_C0|PIT_SQUAREMODE|PIT_READMODE ;
unsigned int clknumb = CLKNUM; /* interrupt interval for timer 0 */
void
-pit_prepare_sleep(int persec)
+pit_prepare_sleep(int usec)
{
/* Prepare to sleep for 1/persec seconds */
- uint32_t val = 0;
+ uint64_t val = 0;
uint8_t lsb, msb;
val = inb(PITAUX_PORT);
@@ -77,7 +77,7 @@ pit_prepare_sleep(int persec)
val |= PITAUX_GATE2;
outb (PITAUX_PORT, val);
outb (PITCTL_PORT, PIT_C2 | PIT_LOADMODE | PIT_ONESHOTMODE);
- val = CLKNUM / persec;
+ val = CLKNUM * usec / 1000000;
lsb = val & 0xff;
msb = val >> 8;
outb (PITCTR2_PORT, lsb);
@@ -104,15 +104,19 @@ pit_sleep(void)
void
pit_udelay(int usec)
{
- pit_prepare_sleep(1000000 / usec);
+ while (usec > MAX_PIT_USEC) {
+ pit_prepare_sleep(MAX_PIT_USEC);
+ pit_sleep();
+ usec -= MAX_PIT_USEC;
+ }
+ pit_prepare_sleep(usec);
pit_sleep();
}
void
pit_mdelay(int msec)
{
- pit_prepare_sleep(1000 / msec);
- pit_sleep();
+ pit_udelay(1000 * msec);
}
void
diff --git a/i386/i386/pit.h b/i386/i386/pit.h
index 49e1051b..350ddc21 100644
--- a/i386/i386/pit.h
+++ b/i386/i386/pit.h
@@ -87,6 +87,9 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#if defined(AT386) || defined(ATX86_64)
#define CLKNUM 1193182
+
+/* CLKNUM ticks/s * (54924/1000000)s ~= 0xffff */
+#define MAX_PIT_USEC 54924
#endif /* AT386 */
extern void clkstart(void);
diff --git a/i386/i386/smp.c b/i386/i386/smp.c
index dc3a8ba5..6b610020 100644
--- a/i386/i386/smp.c
+++ b/i386/i386/smp.c
@@ -23,6 +23,7 @@
#include <i386/smp.h>
#include <i386/cpu.h>
#include <i386/pio.h>
+#include <i386/pit.h>
#include <i386/vm_param.h>
#include <i386at/idt.h>
#include <i386at/cram.h>
@@ -138,13 +139,13 @@ smp_send_ipi_startup_twice(int bsp_apic_id, int vector)
*/
apic_send_ipi(ALL_EXCLUDING_SELF, STARTUP, PHYSICAL, DE_ASSERT, EDGE,
vector, bsp_apic_id);
- hpet_udelay(10);
+ pit_udelay(10);
/* Wait for other cpu to accept IPI */
wait_for_ipi();
send_err = lapic->error_status.r;
- hpet_udelay(10);
+ pit_udelay(10);
lapic->error_status.r = 0;
accept_err = lapic->error_status.r & 0xef;
--
2.51.0