From 24371d2620ba4b36905f86555a9d5793b6deb900 Mon Sep 17 00:00:00 2001 From: robertmh Date: Tue, 5 Aug 2008 20:24:00 +0000 Subject: [PATCH] 2008-08-05 Robert Millan * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pit.c'. * conf/i386-efi.rmk (kernel_mod_SOURCES): Likewise. * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Likewise. Also add `kern/i386/tsc.c', `kern/generic/rtc_get_time_ms.c' and `kern/generic/millisleep.c'. * kern/i386/tsc.c (calibrate_tsc): Rewrite using grub_pit_wait() instead of grub_get_rtc(). (grub_tsc_init): Initialize `tsc_boot_time'. * kern/i386/linuxbios/init.c (grub_millisleep): Remove stub. (grub_machine_init): Use grub_tsc_init() rather than installing an RTC-based handler via grub_install_get_time_ms(). * kern/i386/pit.c: New file. * include/grub/i386/pit.h: Likewise. --- ChangeLog | 19 +++++++++++++++++++ DISTLIST | 2 ++ conf/i386-coreboot.rmk | 3 +++ conf/i386-efi.rmk | 2 +- conf/i386-pc.rmk | 2 +- include/grub/i386/pit.h | 19 +++++++++++++++++++ kern/i386/linuxbios/init.c | 7 +------ kern/i386/pit.c | 39 ++++++++++++++++++++++++++++++++++++++ kern/i386/tsc.c | 39 +++++--------------------------------- 9 files changed, 90 insertions(+), 42 deletions(-) create mode 100644 include/grub/i386/pit.h create mode 100644 kern/i386/pit.c diff --git a/ChangeLog b/ChangeLog index d7d6a820c..85117e75c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2008-08-05 Robert Millan + + * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pit.c'. + * conf/i386-efi.rmk (kernel_mod_SOURCES): Likewise. + * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Likewise. Also add + `kern/i386/tsc.c', `kern/generic/rtc_get_time_ms.c' and + `kern/generic/millisleep.c'. + + * kern/i386/tsc.c (calibrate_tsc): Rewrite using grub_pit_wait() + instead of grub_get_rtc(). + (grub_tsc_init): Initialize `tsc_boot_time'. + + * kern/i386/linuxbios/init.c (grub_millisleep): Remove stub. + (grub_machine_init): Use grub_tsc_init() rather than + installing an RTC-based handler via grub_install_get_time_ms(). + + * kern/i386/pit.c: New file. + * include/grub/i386/pit.h: Likewise. + 2008-08-05 Bean * boot/i386/pc/pxeboot.S (_start): Use drive number 0x7F for pxe. diff --git a/DISTLIST b/DISTLIST index 6a7fffcce..649cb9085 100644 --- a/DISTLIST +++ b/DISTLIST @@ -159,6 +159,7 @@ include/grub/i386/pc/vbefill.h include/grub/i386/pc/vbe.h include/grub/i386/pc/vbeutil.h include/grub/i386/pc/vga.h +include/grub/i386/pit.h include/grub/i386/setjmp.h include/grub/i386/time.h include/grub/i386/types.h @@ -240,6 +241,7 @@ kern/i386/loader.S kern/i386/pc/init.c kern/i386/pc/lzo1x.S kern/i386/pc/startup.S +kern/i386/pit.c kern/i386/realmode.S kern/ieee1275/cmain.c kern/ieee1275/ieee1275.c diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk index c4ca95e8c..5535dab7a 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -18,6 +18,9 @@ kernel_elf_SOURCES = kern/i386/linuxbios/startup.S kern/i386/linuxbios/init.c \ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ kern/time.c \ kern/i386/dl.c kern/parser.c kern/partition.c \ + kern/i386/tsc.c kern/i386/pit.c \ + kern/generic/rtc_get_time_ms.c \ + kern/generic/millisleep.c \ kern/env.c \ term/i386/pc/console.c \ term/i386/pc/at_keyboard.c term/i386/pc/vga_text.c \ diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index e35a5c9a7..a3234b596 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -85,7 +85,7 @@ kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \ kern/i386/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ term/efi/console.c disk/efi/efidisk.c \ - kern/i386/tsc.c \ + kern/i386/tsc.c kern/i386/pit.c \ kern/generic/rtc_get_time_ms.c \ kern/generic/millisleep.c kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 3e8469e00..c1e4ac4a9 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -44,7 +44,7 @@ kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ kern/time.c \ kern/i386/dl.c kern/i386/pc/init.c kern/parser.c kern/partition.c \ - kern/i386/tsc.c \ + kern/i386/tsc.c kern/i386/pit.c \ kern/generic/rtc_get_time_ms.c \ kern/generic/millisleep.c \ kern/env.c \ diff --git a/include/grub/i386/pit.h b/include/grub/i386/pit.h new file mode 100644 index 000000000..7ac0256a2 --- /dev/null +++ b/include/grub/i386/pit.h @@ -0,0 +1,19 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +extern void grub_pit_wait (grub_uint16_t tics); diff --git a/kern/i386/linuxbios/init.c b/kern/i386/linuxbios/init.c index 1d25986b7..0e6567b9d 100644 --- a/kern/i386/linuxbios/init.c +++ b/kern/i386/linuxbios/init.c @@ -60,11 +60,6 @@ grub_stop_floppy (void) grub_outb (0, GRUB_FLOPPY_REG_DIGITAL_OUTPUT); } -void -grub_millisleep (grub_uint32_t ms __attribute__ ((unused))) -{ -} - void grub_exit (void) { @@ -144,7 +139,7 @@ grub_machine_init (void) /* This variable indicates size, not offset. */ grub_upper_mem -= GRUB_MEMORY_MACHINE_UPPER_START; - grub_install_get_time_ms (grub_rtc_get_time_ms); + grub_tsc_init (); } void diff --git a/kern/i386/pit.c b/kern/i386/pit.c new file mode 100644 index 000000000..0dbbf1cd0 --- /dev/null +++ b/kern/i386/pit.c @@ -0,0 +1,39 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include + +#define TIMER2_REG_CONTROL 0x42 +#define TIMER_REG_COMMAND 0x43 +#define TIMER2_REG_LATCH 0x61 + +#define TIMER2_SELECT 0x80 +#define TIMER_ENABLE_LSB 0x20 +#define TIMER_ENABLE_MSB 0x10 +#define TIMER2_LATCH 0x20 + +void +grub_pit_wait (grub_uint16_t tics) +{ + grub_outb (TIMER2_SELECT | TIMER_ENABLE_LSB | TIMER_ENABLE_MSB, TIMER_REG_COMMAND); + grub_outb (tics & 0xff, TIMER2_REG_CONTROL); + grub_outb (tics >> 8, TIMER2_REG_CONTROL); + + while ((grub_inb (TIMER2_REG_LATCH) & TIMER2_LATCH) == 0x00); +} diff --git a/kern/i386/tsc.c b/kern/i386/tsc.c index a142e3d64..458fc0ec9 100644 --- a/kern/i386/tsc.c +++ b/kern/i386/tsc.c @@ -25,8 +25,7 @@ #include #include -/* Calibrated reference for TSC=0. This defines the time since the epoch in - milliseconds that TSC=0 refers to. */ +/* This defines the value TSC had at the epoch (that is, when we calibrated it). */ static grub_uint64_t tsc_boot_time; /* Calibrated TSC rate. (In TSC ticks per millisecond.) */ @@ -47,44 +46,15 @@ grub_tsc_get_time_ms (void) static void calibrate_tsc (void) { - /* First calbrate the TSC rate (relative, not absolute time). */ + /* First calibrate the TSC rate (relative, not absolute time). */ grub_uint64_t start_tsc; grub_uint64_t end_tsc; - grub_uint32_t initial_tick; - grub_uint32_t start_tick; - grub_uint32_t end_tick; - /* Wait for the start of the next tick; - we'll base out timing off this edge. */ - initial_tick = grub_get_rtc (); - do - { - start_tick = grub_get_rtc (); - } - while (start_tick == initial_tick); start_tsc = grub_get_tsc (); - - /* Wait for the start of the next tick. This will - be the end of the 1-tick period. */ - do - { - end_tick = grub_get_rtc (); - } - while (end_tick - start_tick < CALIBRATION_TICKS); + grub_pit_wait (0xffff); end_tsc = grub_get_tsc (); - tsc_ticks_per_ms = - grub_divmod64 (grub_divmod64 - (end_tsc - start_tsc, end_tick - start_tick, 0) - * GRUB_TICKS_PER_SECOND, 1000, 0); - - /* Reference the TSC zero (boot time) to the epoch to - get an absolute real time reference. */ - grub_uint64_t ms_since_boot = grub_divmod64 (end_tsc, tsc_ticks_per_ms, 0); - grub_uint64_t mstime_now = grub_divmod64 ((grub_uint64_t) 1000 * end_tick, - GRUB_TICKS_PER_SECOND, - 0); - tsc_boot_time = mstime_now - ms_since_boot; + tsc_ticks_per_ms = grub_divmod64 (end_tsc - start_tsc, 55, 0); } void @@ -92,6 +62,7 @@ grub_tsc_init (void) { if (grub_cpu_is_tsc_supported ()) { + tsc_boot_time = grub_get_tsc (); calibrate_tsc (); grub_install_get_time_ms (grub_tsc_get_time_ms); }