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



Reply via email to