# # # add_file "kern/i386/linuxbios/rdtsc.h" # content [5832e2e7e54082d9dab45ea69f17e39843d032f0] # # add_file "kern/i386/linuxbios/timer.c" # content [9f2d6a01c2189f368072bbd2fa984caaf34e678d] # # patch "conf/i386-linuxbios.rmk" # from [cfe28b0d50c0dbccaace29be109288013500eff1] # to [d42ea1a8c5301eef52069f406fbdee26d8e13365] # # patch "kern/i386/linuxbios/init.c" # from [8433bc623ac7bcff3641e4ff9c5605c7346f7544] # to [d7e5bc0d6af8c62ddbbdf6a8d9df9040bd3b3572] # ============================================================ --- kern/i386/linuxbios/rdtsc.h 5832e2e7e54082d9dab45ea69f17e39843d032f0 +++ kern/i386/linuxbios/rdtsc.h 5832e2e7e54082d9dab45ea69f17e39843d032f0 @@ -0,0 +1,40 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _RDTSC_H_ +#define _RDTSC_H_ + +static inline unsigned long long rdtsc(void) +{ + unsigned long long val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; +} + +#endif ============================================================ --- kern/i386/linuxbios/timer.c 9f2d6a01c2189f368072bbd2fa984caaf34e678d +++ kern/i386/linuxbios/timer.c 9f2d6a01c2189f368072bbd2fa984caaf34e678d @@ -0,0 +1,91 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "rdtsc.h" + +#define outb grub_outb +#define inb grub_inb + +static unsigned int cpu_khz; + +/** + * Calculate the speed of the processor for use in delays. + * + * @return The CPU speed in kHz. + */ +unsigned int get_cpu_speed(void) +{ + unsigned long long start, end; + + /* Set up the PPC port - disable the speaker, enable the T2 gate. */ + outb((inb(0x61) & ~0x02) | 0x01, 0x61); + + /* Set the PIT to Mode 0, counter 2, word access. */ + outb(0xB0, 0x43); + + /* Load the counter with 0xffff. */ + outb(0xff, 0x42); + outb(0xff, 0x42); + + /* Read the number of ticks during the period. */ + start = rdtsc(); + while (!(inb(0x61) & 0x20)) ; + end = rdtsc(); + + /* + * The clock rate is 1193180 Hz, the number of milliseconds for a + * period of 0xffff is 1193180 / (0xFFFF * 1000) or .0182. + * Multiply that by the number of measured clocks to get the kHz value. + */ + cpu_khz = (unsigned int)((end - start) * 1193180U / (1000 * 0xffff)); + + return cpu_khz; +} + +static inline void _delay(unsigned int delta) +{ + unsigned long long timeout = rdtsc() + delta; + while (rdtsc() < timeout) ; +} + +void ndelay(unsigned int n) +{ + _delay(n * cpu_khz / 1000000); +} + +void mdelay(unsigned int m) +{ + _delay(m * cpu_khz); +} + +void delay(unsigned int s) +{ + _delay(s * cpu_khz * 1000); +} ============================================================ --- conf/i386-linuxbios.rmk cfe28b0d50c0dbccaace29be109288013500eff1 +++ conf/i386-linuxbios.rmk d42ea1a8c5301eef52069f406fbdee26d8e13365 @@ -16,6 +16,7 @@ kernel_elf_SOURCES = kern/i386/linuxbios # For kernel.elf. kernel_elf_SOURCES = kern/i386/linuxbios/startup.S kern/i386/linuxbios/init.c \ kern/i386/linuxbios/table.c \ + kern/i386/linuxbios/timer.c \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \ ============================================================ --- kern/i386/linuxbios/init.c 8433bc623ac7bcff3641e4ff9c5605c7346f7544 +++ kern/i386/linuxbios/init.c d7e5bc0d6af8c62ddbbdf6a8d9df9040bd3b3572 @@ -52,7 +52,7 @@ grub_get_rtc (void) grub_uint32_t grub_get_rtc (void) { - return grub_time_tics; + return grub_time_tics++; } /* Stop the floppy drive from spinning, so that other software is @@ -63,9 +63,13 @@ grub_stop_floppy (void) grub_outb (0, GRUB_FLOPPY_REG_DIGITAL_OUTPUT); } +extern unsigned int get_cpu_speed(void); +extern void mdelay(unsigned int m); + void -grub_millisleep (grub_uint32_t ms __attribute__ ((unused))) +grub_millisleep (grub_uint32_t ms) { + mdelay(ms); } void @@ -96,6 +100,8 @@ grub_machine_init (void) grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE; grub_upper_mem = 0; + get_cpu_speed(); + // assume 256kb image, v3 style // TODO: check for LAR presence and be more clever in general *memdisk_addr = 0xc0000;