Browse Source

[timer] Formalise the timer API

We now have two implementations for the timer API: one using the
time-of-day counter at 40:70 and one using RDTSC.  Both make use of
timer2_udelay().
tags/v0.9.6
Michael Brown 16 years ago
parent
commit
16f1e35775

+ 87
- 0
src/arch/i386/core/rdtsc_timer.c View File

@@ -0,0 +1,87 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+/** @file
20
+ *
21
+ * RDTSC timer
22
+ *
23
+ */
24
+
25
+#include <assert.h>
26
+#include <gpxe/timer.h>
27
+#include <gpxe/timer2.h>
28
+
29
+/**
30
+ * Number of TSC ticks per microsecond
31
+ *
32
+ * This is calibrated on the first use of the timer.
33
+ */
34
+static unsigned long rdtsc_ticks_per_usec;
35
+
36
+/**
37
+ * Delay for a fixed number of microseconds
38
+ *
39
+ * @v usecs		Number of microseconds for which to delay
40
+ */
41
+static void rdtsc_udelay ( unsigned long usecs ) {
42
+	unsigned long start;
43
+	unsigned long elapsed;
44
+
45
+	/* Sanity guard, since we may divide by this */
46
+	if ( ! usecs )
47
+		usecs = 1;
48
+
49
+	start = currticks();
50
+	if ( rdtsc_ticks_per_usec ) {
51
+		/* Already calibrated; busy-wait until done */
52
+		do {
53
+			elapsed = ( currticks() - start );
54
+		} while ( elapsed < ( usecs * rdtsc_ticks_per_usec ) );
55
+	} else {
56
+		/* Not yet calibrated; use timer2 and calibrate
57
+		 * based on result.
58
+		 */
59
+		timer2_udelay ( usecs );
60
+		elapsed = ( currticks() - start );
61
+		rdtsc_ticks_per_usec = ( elapsed / usecs );
62
+		DBG ( "RDTSC timer calibrated: %ld ticks in %ld usecs "
63
+		      "(%ld MHz)\n", elapsed, usecs,
64
+		      ( rdtsc_ticks_per_usec << TSC_SHIFT ) );
65
+	}
66
+}
67
+
68
+/**
69
+ * Get number of ticks per second
70
+ *
71
+ * @ret ticks_per_sec	Number of ticks per second
72
+ */
73
+static unsigned long rdtsc_ticks_per_sec ( void ) {
74
+
75
+	/* Calibrate timer, if not already done */
76
+	if ( ! rdtsc_ticks_per_usec )
77
+		udelay ( 1 );
78
+
79
+	/* Sanity check */
80
+	assert ( rdtsc_ticks_per_usec != 0 );
81
+
82
+	return ( rdtsc_ticks_per_usec * 1000 * 1000 );
83
+}
84
+
85
+PROVIDE_TIMER ( rdtsc, udelay, rdtsc_udelay );
86
+PROVIDE_TIMER_INLINE ( rdtsc, currticks );
87
+PROVIDE_TIMER ( rdtsc, ticks_per_sec, rdtsc_ticks_per_sec );

src/arch/i386/core/i386_timer.c → src/arch/i386/core/timer2.c View File

@@ -12,12 +12,11 @@
12 12
  */
13 13
 
14 14
 #include <stddef.h>
15
-#include <bits/timer2.h>
16
-#include <gpxe/timer.h>
15
+#include <gpxe/timer2.h>
17 16
 #include <gpxe/io.h>
18 17
 
19 18
 /* Timers tick over at this rate */
20
-#define TIMER2_TICK_RATE	1193180U
19
+#define TIMER2_TICKS_PER_SEC	1193180U
21 20
 
22 21
 /* Parallel Peripheral Controller Port B */
23 22
 #define	PPC_PORTB	0x61
@@ -52,8 +51,7 @@
52 51
 #define	BINARY_COUNT	0x00
53 52
 #define	BCD_COUNT	0x01
54 53
 
55
-static void load_timer2(unsigned int ticks)
56
-{
54
+static void load_timer2 ( unsigned int ticks ) {
57 55
 	/*
58 56
 	 * Now let's take care of PPC channel 2
59 57
 	 *
@@ -75,15 +73,13 @@ static void load_timer2(unsigned int ticks)
75 73
 	outb(ticks >> 8, TIMER2_PORT);
76 74
 }
77 75
 
78
-static int timer2_running(void)
79
-{
76
+static int timer2_running ( void ) {
80 77
 	return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
81 78
 }
82 79
 
83
-void i386_timer2_udelay(unsigned int usecs)
84
-{
85
-		load_timer2((usecs * TIMER2_TICK_RATE)/USECS_IN_SEC);
86
-		while (timer2_running())
87
-			;
80
+void timer2_udelay ( unsigned long usecs ) {
81
+	load_timer2 ( ( usecs * TIMER2_TICKS_PER_SEC ) / ( 1000 * 1000 ) );
82
+	while (timer2_running()) {
83
+		/* Do nothing */
84
+	}
88 85
 }
89
-

+ 0
- 57
src/arch/i386/drivers/timer_bios.c View File

@@ -1,57 +0,0 @@
1
-/*
2
- * Etherboot routines for PCBIOS firmware.
3
- *
4
- * Body of routines taken from old pcbios.S
5
- */
6
-
7
-#include <gpxe/init.h>
8
-#include <gpxe/timer.h>
9
-#include <stdio.h>
10
-#include <realmode.h>
11
-#include <bios.h>
12
-#include <bits/timer2.h>
13
-
14
-/* A bit faster actually, but we don't care. */
15
-#define	TIMER2_TICKS_PER_SEC	18
16
-
17
-/*
18
- * Use direct memory access to BIOS variables, longword 0040:006C (ticks
19
- * today) and byte 0040:0070 (midnight crossover flag) instead of calling
20
- * timeofday BIOS interrupt.
21
- */
22
-
23
-static tick_t bios_currticks ( void ) {
24
-	static int days = 0;
25
-	uint32_t ticks;
26
-	uint8_t midnight;
27
-
28
-	/* Re-enable interrupts so that the timer interrupt can occur */
29
-	__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
30
-					   "nop\n\t"
31
-					   "nop\n\t"
32
-					   "cli\n\t" ) : : );
33
-
34
-	get_real ( ticks, BDA_SEG, 0x006c );
35
-	get_real ( midnight, BDA_SEG, 0x0070 );
36
-
37
-	if ( midnight ) {
38
-		midnight = 0;
39
-		put_real ( midnight, BDA_SEG, 0x0070 );
40
-		days += 0x1800b0;
41
-	}
42
-
43
-	return ( (days + ticks) * (USECS_IN_SEC / TIMER2_TICKS_PER_SEC) );
44
-}
45
-
46
-static int bios_ts_init(void)
47
-{
48
-	DBG("BIOS timer installed\n");
49
-	return 0;
50
-}
51
-
52
-struct timer bios_ts __timer ( 02 ) = {
53
-	.init = bios_ts_init,
54
-	.udelay = i386_timer2_udelay,
55
-	.currticks = bios_currticks,
56
-};
57
-

+ 0
- 69
src/arch/i386/drivers/timer_rdtsc.c View File

@@ -1,69 +0,0 @@
1
-
2
-#include <gpxe/init.h>
3
-#include <gpxe/timer.h>
4
-#include <errno.h>
5
-#include <stdio.h>
6
-#include <bits/cpu.h>
7
-#include <bits/timer2.h>
8
-#include <gpxe/io.h>
9
-
10
-
11
-#define rdtsc(low,high) \
12
-     __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
13
-
14
-#define rdtscll(val) \
15
-     __asm__ __volatile__ ("rdtsc" : "=A" (val))
16
-
17
-
18
-/* Measure how many clocks we get in one microsecond */
19
-static inline uint64_t calibrate_tsc(void)
20
-{
21
-
22
-	uint64_t rdtsc_start;
23
-	uint64_t rdtsc_end;
24
-
25
-	rdtscll(rdtsc_start);
26
-	i386_timer2_udelay(USECS_IN_MSEC);
27
-	rdtscll(rdtsc_end);
28
-	
29
-	return (rdtsc_end - rdtsc_start) / USECS_IN_MSEC;
30
-}
31
-
32
-static uint32_t clocks_per_usec = 0;
33
-
34
-/* We measure time in microseconds. */
35
-static tick_t rdtsc_currticks(void)
36
-{
37
-	uint64_t clocks;
38
-
39
-	/* Read the Time Stamp Counter */
40
-	rdtscll(clocks);
41
-
42
-	return clocks / clocks_per_usec;
43
-}
44
-
45
-static int rdtsc_ts_init(void)
46
-{
47
-
48
-	struct cpuinfo_x86 cpu_info;
49
-
50
-	get_cpuinfo(&cpu_info);
51
-	if (cpu_info.features & X86_FEATURE_TSC) {
52
-		clocks_per_usec= calibrate_tsc();
53
-		if (clocks_per_usec) {
54
-			DBG("RDTSC ticksource installed. CPU running at %ld Mhz\n",
55
-				clocks_per_usec);
56
-			return 0;
57
-		}
58
-	}
59
-
60
-	DBG("RDTSC ticksource not available on this machine.\n");
61
-	return -ENODEV;
62
-}
63
-
64
-struct timer rdtsc_ts __timer (01) = {
65
-	.init = rdtsc_ts_init,
66
-	.udelay = generic_currticks_udelay,
67
-	.currticks = rdtsc_currticks,
68
-};
69
-

+ 0
- 1
src/arch/i386/include/bios.h View File

@@ -5,7 +5,6 @@
5 5
 #define BDA_FBMS 0x0013
6 6
 #define BDA_NUM_DRIVES 0x0075
7 7
 
8
-extern unsigned long currticks ( void );
9 8
 extern void cpu_nap ( void );
10 9
 
11 10
 #endif /* BIOS_H */

+ 13
- 0
src/arch/i386/include/bits/timer.h View File

@@ -0,0 +1,13 @@
1
+#ifndef _BITS_TIMER_H
2
+#define _BITS_TIMER_H
3
+
4
+/** @file
5
+ *
6
+ * i386-specific timer API implementations
7
+ *
8
+ */
9
+
10
+#include <gpxe/bios_timer.h>
11
+#include <gpxe/rdtsc_timer.h>
12
+
13
+#endif /* _BITS_TIMER_H */

+ 0
- 8
src/arch/i386/include/bits/timer2.h View File

@@ -1,8 +0,0 @@
1
-#ifndef BITS_TIMER2_H
2
-#define BITS_TIMER2_H
3
-
4
-#include <stddef.h>
5
-
6
-void i386_timer2_udelay(unsigned int usecs);
7
-
8
-#endif

+ 42
- 0
src/arch/i386/include/gpxe/bios_timer.h View File

@@ -0,0 +1,42 @@
1
+#ifndef _GPXE_BIOS_TIMER_H
2
+#define _GPXE_BIOS_TIMER_H
3
+
4
+/** @file
5
+ *
6
+ * BIOS timer
7
+ *
8
+ */
9
+
10
+#ifdef TIMER_PCBIOS
11
+#define TIMER_PREFIX_pcbios
12
+#else
13
+#define TIMER_PREFIX_pcbios __pcbios_
14
+#endif
15
+
16
+#include <gpxe/timer2.h>
17
+
18
+/**
19
+ * Delay for a fixed number of microseconds
20
+ *
21
+ * @v usecs		Number of microseconds for which to delay
22
+ */
23
+static inline __always_inline void
24
+TIMER_INLINE ( pcbios, udelay ) ( unsigned long usecs ) {
25
+	/* BIOS timer is not high-resolution enough for udelay(), so
26
+	 * we use timer2
27
+	 */
28
+	timer2_udelay ( usecs );
29
+}
30
+
31
+/**
32
+ * Get number of ticks per second
33
+ *
34
+ * @ret ticks_per_sec	Number of ticks per second
35
+ */
36
+static inline __always_inline unsigned long
37
+TIMER_INLINE ( pcbios, ticks_per_sec ) ( void ) {
38
+	/* BIOS timer ticks over at 18.2 ticks per second */
39
+	return 18;
40
+}
41
+
42
+#endif /* _GPXE_BIOS_TIMER_H */

+ 37
- 0
src/arch/i386/include/gpxe/rdtsc_timer.h View File

@@ -0,0 +1,37 @@
1
+#ifndef _GPXE_RDTSC_TIMER_H
2
+#define _GPXE_RDTSC_TIMER_H
3
+
4
+/** @file
5
+ *
6
+ * RDTSC timer
7
+ *
8
+ */
9
+
10
+#ifdef TIMER_RDTSC
11
+#define TIMER_PREFIX_rdtsc
12
+#else
13
+#define TIMER_PREFIX_rdtsc __rdtsc_
14
+#endif
15
+
16
+/**
17
+ * RDTSC values can easily overflow an unsigned long.  We discard the
18
+ * low-order bits in order to obtain sensibly-scaled values.
19
+ */
20
+#define TSC_SHIFT 8
21
+
22
+/**
23
+ * Get current system time in ticks
24
+ *
25
+ * @ret ticks		Current time, in ticks
26
+ */
27
+static inline __always_inline unsigned long
28
+TIMER_INLINE ( rdtsc, currticks ) ( void ) {
29
+	unsigned long ticks;
30
+
31
+	__asm__ __volatile__ ( "rdtsc\n\t"
32
+			       "shrdl %1, %%edx, %%eax\n\t"
33
+			       : "=a" ( ticks ) : "i" ( TSC_SHIFT ) : "edx" );
34
+	return ticks;
35
+}
36
+
37
+#endif /* _GPXE_RDTSC_TIMER_H */

+ 12
- 0
src/arch/i386/include/gpxe/timer2.h View File

@@ -0,0 +1,12 @@
1
+#ifndef _GPXE_TIMER2_H
2
+#define _GPXE_TIMER2_H
3
+
4
+/** @file
5
+ *
6
+ * Timer chip control
7
+ *
8
+ */
9
+
10
+extern void timer2_udelay ( unsigned long usecs );
11
+
12
+#endif /* _GPXE_TIMER2_H */

+ 63
- 0
src/arch/i386/interface/pcbios/bios_timer.c View File

@@ -0,0 +1,63 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+/** @file
20
+ *
21
+ * BIOS timer
22
+ *
23
+ */
24
+
25
+#include <gpxe/timer.h>
26
+#include <realmode.h>
27
+#include <bios.h>
28
+
29
+/**
30
+ * Get current system time in ticks
31
+ *
32
+ * @ret ticks		Current time, in ticks
33
+ *
34
+ * Use direct memory access to BIOS variables, longword 0040:006C
35
+ * (ticks today) and byte 0040:0070 (midnight crossover flag) instead
36
+ * of calling timeofday BIOS interrupt.
37
+ */
38
+static unsigned long bios_currticks ( void ) {
39
+	static int days = 0;
40
+	uint32_t ticks;
41
+	uint8_t midnight;
42
+
43
+	/* Re-enable interrupts so that the timer interrupt can occur */
44
+	__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
45
+					   "nop\n\t"
46
+					   "nop\n\t"
47
+					   "cli\n\t" ) : : );
48
+
49
+	get_real ( ticks, BDA_SEG, 0x006c );
50
+	get_real ( midnight, BDA_SEG, 0x0070 );
51
+
52
+	if ( midnight ) {
53
+		midnight = 0;
54
+		put_real ( midnight, BDA_SEG, 0x0070 );
55
+		days += 0x1800b0;
56
+	}
57
+
58
+	return ( days + ticks );
59
+}
60
+
61
+PROVIDE_TIMER_INLINE ( pcbios, udelay );
62
+PROVIDE_TIMER ( pcbios, currticks, bios_currticks );
63
+PROVIDE_TIMER_INLINE ( pcbios, ticks_per_sec );

+ 1
- 0
src/config/defaults/pcbios.h View File

@@ -9,6 +9,7 @@
9 9
 
10 10
 #define IOAPI_X86
11 11
 #define PCIAPI_PCBIOS
12
+#define TIMER_PCBIOS
12 13
 #define CONSOLE_PCBIOS
13 14
 
14 15
 #endif /* CONFIG_DEFAULTS_PCBIOS_H */

+ 15
- 0
src/config/timer.h View File

@@ -0,0 +1,15 @@
1
+#ifndef CONFIG_TIMER_H
2
+#define CONFIG_TIMER_H
3
+
4
+/** @file
5
+ *
6
+ * Timer configuration.
7
+ *
8
+ */
9
+
10
+#include <config/defaults.h>
11
+
12
+//#undef		TIMER_PCBIOS
13
+//#define		TIMER_RDTSC
14
+
15
+#endif /* CONFIG_TIMER_H */

+ 4
- 2
src/core/monojob.c View File

@@ -63,7 +63,8 @@ struct job_interface monojob = {
63 63
 int monojob_wait ( const char *string ) {
64 64
 	int key;
65 65
 	int rc;
66
-	tick_t last_progress_dot;
66
+	unsigned long last_progress_dot;
67
+	unsigned long elapsed;
67 68
 
68 69
 	printf ( "%s.", string );
69 70
 	monojob_rc = -EINPROGRESS;
@@ -81,7 +82,8 @@ int monojob_wait ( const char *string ) {
81 82
 				break;
82 83
 			}
83 84
 		}
84
-		if ( ( currticks() - last_progress_dot ) > TICKS_PER_SEC ) {
85
+		elapsed = ( currticks() - last_progress_dot );
86
+		if ( elapsed > TICKS_PER_SEC ) {
85 87
 			printf ( "." );
86 88
 			last_progress_dot = currticks();
87 89
 		}

+ 9
- 82
src/core/timer.c View File

@@ -1,7 +1,5 @@
1 1
 /*
2
- * core/timer.c
3
- *
4
- * Copyright (C) 2007 Alexey Zaytsev <alexey.zaytsev@gmail.com>
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
5 3
  *
6 4
  * This program is free software; you can redistribute it and/or
7 5
  * modify it under the terms of the GNU General Public License as
@@ -18,96 +16,25 @@
18 16
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 17
  */
20 18
 
21
-#include <stddef.h>
22
-#include <assert.h>
23
-#include <gpxe/timer.h>
24
-
25
-static struct timer ts_table[0]
26
-	__table_start ( struct timer, timers );
27
-static struct timer ts_table_end[0]
28
-	__table_end ( struct timer, timers );
29
-
30
-/*
31
- * This function may be used in custom timer driver.
32
- *
33
- * This udelay implementation works well if you've got a
34
- * fast currticks().
35
- */
36
-void generic_currticks_udelay ( unsigned int usecs ) {
37
-	tick_t start;
38
-	tick_t elapsed;
39
-	
40
-	start = currticks();
41
-	do {
42
-		/* xxx: Relax the cpu some way. */
43
-		elapsed = ( currticks() - start );
44
-	} while ( elapsed < usecs );
45
-}
46
-
47
-/**
48
- * Identify timer source
49
- *
50
- * @ret timer		Timer source
51
- */
52
-static struct timer * timer ( void ) {
53
-	static struct timer *ts = NULL;
54
-
55
-	/* If we have a timer, use it */
56
-	if ( ts )
57
-		return ts;
58
-
59
-	/* Scan for a usable timer */
60
-	for ( ts = ts_table ; ts < ts_table_end ; ts++ ) {
61
-		if ( ts->init() == 0 )
62
-			return ts;
63
-	}
64
-
65
-	/* No timer found; we cannot continue */
66
-	assert ( 0 );
67
-	while ( 1 ) {};
68
-}
69
-
70
-/**
71
- * Read current time
72
- *
73
- * @ret ticks	Current time, in ticks
74
- */
75
-tick_t currticks ( void ) {
76
-	tick_t ct;
77
-
78
-	ct = timer()->currticks();
79
-	DBG ( "currticks: %ld.%06ld seconds\n",
80
-	      ct / USECS_IN_SEC, ct % USECS_IN_SEC );
81
-
82
-	return ct;
83
-}
84
-
85
-/**
86
- * Delay
87
- *
88
- * @v usecs	Time to delay, in microseconds
89
- */
90
-void udelay ( unsigned int usecs ) {
91
-	timer()->udelay ( usecs );
92
-}
19
+#include <unistd.h>
93 20
 
94 21
 /**
95
- * Delay
22
+ * Delay for a fixed number of milliseconds
96 23
  *
97
- * @v msecs	Time to delay, in milliseconds
24
+ * @v msecs		Number of milliseconds for which to delay
98 25
  */
99
-void mdelay ( unsigned int msecs ) {
26
+void mdelay ( unsigned long msecs ) {
100 27
 	while ( msecs-- )
101
-		udelay ( USECS_IN_MSEC );
28
+		udelay ( 1000 );
102 29
 }
103 30
 
104 31
 /**
105
- * Delay
32
+ * Delay for a fixed number of seconds
106 33
  *
107
- * @v secs	Time to delay, in seconds
34
+ * @v secs		Number of seconds for which to delay
108 35
  */
109 36
 unsigned int sleep ( unsigned int secs ) {
110 37
 	while ( secs-- )
111
-		mdelay ( MSECS_IN_SEC );
38
+		mdelay ( 1000 );
112 39
 	return 0;
113 40
 }

+ 2
- 2
src/drivers/net/3c90x.c View File

@@ -497,7 +497,7 @@ a3c90x_transmit(struct nic *nic __unused, const char *d, unsigned int t,
497 497
 
498 498
     unsigned char status;
499 499
     unsigned i, retries;
500
-    tick_t ct;
500
+    unsigned long ct;
501 501
 
502 502
     for (retries=0; retries < XMIT_RETRIES ; retries++)
503 503
 	{
@@ -543,7 +543,7 @@ a3c90x_transmit(struct nic *nic __unused, const char *d, unsigned int t,
543 543
 	ct = currticks();
544 544
 
545 545
 	while (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004) &&
546
-		ct + 10*USECS_IN_MSEC < currticks());
546
+		ct + 10*1000 < currticks());
547 547
 		;
548 548
 
549 549
 	if (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004))

+ 4
- 4
src/drivers/net/eepro100.c View File

@@ -407,7 +407,7 @@ static void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, un
407 407
 	} hdr;
408 408
 	unsigned short status;
409 409
 	int s1, s2;
410
-	tick_t ct;
410
+	unsigned long ct;
411 411
 
412 412
 	status = inw(ioaddr + SCBStatus);
413 413
 	/* Acknowledge all of the current interrupt sources ASAP. */
@@ -448,7 +448,7 @@ static void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, un
448 448
 
449 449
 	ct = currticks();
450 450
 	/* timeout 10 ms for transmit */
451
-	while (!txfd.status && ct + 10*USECS_IN_MSEC)
451
+	while (!txfd.status && ct + 10*1000)
452 452
 		/* Wait */;
453 453
 	s2 = inw (ioaddr + SCBStatus);
454 454
 
@@ -608,7 +608,7 @@ static int eepro100_probe ( struct nic *nic, struct pci_device *pci ) {
608 608
 	int read_cmd, ee_size;
609 609
 	int options;
610 610
 	int rx_mode;
611
-	tick_t ct;
611
+	unsigned long ct;
612 612
 
613 613
 	/* we cache only the first few words of the EEPROM data
614 614
 	   be careful not to access beyond this array */
@@ -753,7 +753,7 @@ static int eepro100_probe ( struct nic *nic, struct pci_device *pci ) {
753 753
 	whereami ("started TX thingy (config, iasetup).");
754 754
 
755 755
 	ct = currticks();
756
-	while (!txfd.status && ct + 10*USECS_IN_MSEC < currticks())
756
+	while (!txfd.status && ct + 10*1000 < currticks())
757 757
 		/* Wait */;
758 758
 
759 759
 	/* Read the status register once to disgard stale data */

+ 2
- 2
src/drivers/net/epic100.c View File

@@ -309,7 +309,7 @@ epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
309 309
     unsigned short nstype;
310 310
     unsigned char *txp;
311 311
     int entry;
312
-    tick_t ct;
312
+    unsigned long ct;
313 313
 
314 314
     /* Calculate the next Tx descriptor entry. */
315 315
     entry = cur_tx % TX_RING_SIZE;
@@ -352,7 +352,7 @@ epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
352 352
     ct = currticks();
353 353
     /* timeout 10 ms for transmit */
354 354
     while ((le32_to_cpu(tx_ring[entry].status) & (TRING_OWN)) &&
355
-		ct + 10*USECS_IN_MSEC < currticks())
355
+		ct + 10*1000 < currticks())
356 356
 	/* Wait */;
357 357
 
358 358
     if ((le32_to_cpu(tx_ring[entry].status) & TRING_OWN) != 0)

+ 7
- 7
src/drivers/net/via-rhine.c View File

@@ -784,7 +784,7 @@ ReadMII (int byMIIIndex, int ioaddr)
784 784
     char byMIIAdrbak;
785 785
     char byMIICRbak;
786 786
     char byMIItemp;
787
-    tick_t ct;
787
+    unsigned long ct;
788 788
 
789 789
     byMIIAdrbak = inb (byMIIAD);
790 790
     byMIICRbak = inb (byMIICR);
@@ -800,7 +800,7 @@ ReadMII (int byMIIIndex, int ioaddr)
800 800
     byMIItemp = byMIItemp & 0x40;
801 801
 
802 802
     ct = currticks();
803
-    while (byMIItemp != 0 && ct + 2*USECS_IN_MSEC < currticks())
803
+    while (byMIItemp != 0 && ct + 2*1000 < currticks())
804 804
     {
805 805
 	byMIItemp = inb (byMIICR);
806 806
 	byMIItemp = byMIItemp & 0x40;
@@ -825,7 +825,7 @@ WriteMII (char byMIISetByte, char byMIISetBit, char byMIIOP, int ioaddr)
825 825
     char byMIIAdrbak;
826 826
     char byMIICRbak;
827 827
     char byMIItemp;
828
-    tick_t ct;
828
+    unsigned long ct;
829 829
 
830 830
 
831 831
     byMIIAdrbak = inb (byMIIAD);
@@ -842,7 +842,7 @@ WriteMII (char byMIISetByte, char byMIISetBit, char byMIIOP, int ioaddr)
842 842
     byMIItemp = byMIItemp & 0x40;
843 843
 
844 844
     ct = currticks();
845
-    while (byMIItemp != 0 && ct + 2*USECS_IN_MSEC < currticks())
845
+    while (byMIItemp != 0 && ct + 2*1000 < currticks())
846 846
     {
847 847
 	byMIItemp = inb (byMIICR);
848 848
 	byMIItemp = byMIItemp & 0x40;
@@ -872,7 +872,7 @@ WriteMII (char byMIISetByte, char byMIISetBit, char byMIIOP, int ioaddr)
872 872
     byMIItemp = byMIItemp & 0x20;
873 873
 
874 874
     ct = currticks();
875
-    while (byMIItemp != 0 && ct + 2*USECS_IN_MSEC < currticks())
875
+    while (byMIItemp != 0 && ct + 2*1000 < currticks())
876 876
     {
877 877
 	byMIItemp = inb (byMIICR);
878 878
 	byMIItemp = byMIItemp & 0x20;
@@ -1346,7 +1346,7 @@ rhine_transmit (struct nic *nic,
1346 1346
     unsigned char CR1bak;
1347 1347
     unsigned char CR0bak;
1348 1348
     unsigned int nstype;
1349
-    tick_t ct;
1349
+    unsigned long ct;
1350 1350
 
1351 1351
 
1352 1352
     /*printf ("rhine_transmit\n"); */
@@ -1390,7 +1390,7 @@ rhine_transmit (struct nic *nic,
1390 1390
 	ct = currticks();
1391 1391
         /* Wait until transmit is finished or timeout*/
1392 1392
         while((tp->tx_ring[entry].tx_status.bits.own_bit !=0) &&
1393
-		ct + 10*USECS_IN_MSEC < currticks())
1393
+		ct + 10*1000 < currticks())
1394 1394
         ;
1395 1395
 
1396 1396
         if(tp->tx_ring[entry].tx_status.bits.terr == 0)

+ 2
- 2
src/drivers/net/w89c840.c View File

@@ -112,7 +112,7 @@ static const char *w89c840_version = "driver Version 0.94 - December 12, 2003";
112 112
 
113 113
 /* Operational parameters that usually are not changed. */
114 114
 /* Time in jiffies before concluding the transmitter is hung. */
115
-#define TX_TIMEOUT  (10*USECS_IN_MSEC)
115
+#define TX_TIMEOUT  (10*1000)
116 116
 
117 117
 #define PKT_BUF_SZ  1536  /* Size of each temporary Rx buffer.*/
118 118
 
@@ -486,7 +486,7 @@ static void w89c840_transmit(
486 486
     /* send the packet to destination */
487 487
     unsigned entry;
488 488
     int transmit_status;
489
-    tick_t ct;
489
+    unsigned long ct;
490 490
 
491 491
     /* Caution: the write order is important here, set the field
492 492
        with the "ownership" bits last. */

+ 63
- 31
src/include/gpxe/timer.h View File

@@ -1,41 +1,73 @@
1
-#ifndef	GPXE_TIMER_H
2
-#define GPXE_TIMER_H
1
+#ifndef	_GPXE_TIMER_H
2
+#define _GPXE_TIMER_H
3 3
 
4
-#include <stddef.h>
5
-#include <gpxe/tables.h>
4
+/** @file
5
+ *
6
+ * gPXE timer API
7
+ *
8
+ * The timer API provides udelay() for fixed delays, and currticks()
9
+ * for a monotonically increasing tick counter.
10
+ */
6 11
 
7
-typedef unsigned long tick_t;
12
+#include <gpxe/api.h>
13
+#include <config/timer.h>
8 14
 
9
-#define MSECS_IN_SEC (1000)
10
-#define USECS_IN_SEC (1000*1000)
11
-#define USECS_IN_MSEC (1000)
15
+/**
16
+ * Calculate static inline timer API function name
17
+ *
18
+ * @v _prefix		Subsystem prefix
19
+ * @v _api_func		API function
20
+ * @ret _subsys_func	Subsystem API function
21
+ */
22
+#define TIMER_INLINE( _subsys, _api_func ) \
23
+	SINGLE_API_INLINE ( TIMER_PREFIX_ ## _subsys, _api_func )
12 24
 
13
-#define	TICKS_PER_SEC	USECS_IN_SEC
25
+/**
26
+ * Provide a timer API implementation
27
+ *
28
+ * @v _prefix		Subsystem prefix
29
+ * @v _api_func		API function
30
+ * @v _func		Implementing function
31
+ */
32
+#define PROVIDE_TIMER( _subsys, _api_func, _func ) \
33
+	PROVIDE_SINGLE_API ( TIMER_PREFIX_ ## _subsys, _api_func, _func )
14 34
 
15
-extern tick_t currticks ( void );
35
+/**
36
+ * Provide a static inline timer API implementation
37
+ *
38
+ * @v _prefix		Subsystem prefix
39
+ * @v _api_func		API function
40
+ */
41
+#define PROVIDE_TIMER_INLINE( _subsys, _api_func ) \
42
+	PROVIDE_SINGLE_API_INLINE ( TIMER_PREFIX_ ## _subsys, _api_func )
16 43
 
17
-extern void generic_currticks_udelay ( unsigned int usecs );
44
+/* Include all architecture-independent I/O API headers */
18 45
 
19
-/** A timer */
20
-struct timer {
21
-	/** Initialise timer
22
-	 *
23
-	 * @ret rc	Return status code
24
-	 */
25
-	int ( * init ) ( void );
26
-	/** Read current time
27
-	 *
28
-	 * @ret ticks	Current time, in ticks
29
-	 */
30
-	tick_t ( * currticks ) ( void );
31
-	/** Delay
32
-	 *
33
-	 * @v usecs	Time to delay, in microseconds
34
-	 */
35
-	void ( * udelay ) ( unsigned int usecs );
36
-};
46
+/* Include all architecture-dependent I/O API headers */
47
+#include <bits/timer.h>
37 48
 
38
-#define __timer( order ) __table ( struct timer, timers, order )
49
+/**
50
+ * Delay for a fixed number of microseconds
51
+ *
52
+ * @v usecs		Number of microseconds for which to delay
53
+ */
54
+void udelay ( unsigned long usecs );
39 55
 
40
-#endif	/* GPXE_TIMER_H */
56
+/**
57
+ * Get current system time in ticks
58
+ *
59
+ * @ret ticks		Current time, in ticks
60
+ */
61
+unsigned long currticks ( void );
41 62
 
63
+/**
64
+ * Get number of ticks per second
65
+ *
66
+ * @ret ticks_per_sec	Number of ticks per second
67
+ */
68
+unsigned long ticks_per_sec ( void );
69
+
70
+/** Number of ticks per second */
71
+#define TICKS_PER_SEC ( ticks_per_sec() )
72
+
73
+#endif /* _GPXE_TIMER_H */

+ 14
- 4
src/include/unistd.h View File

@@ -4,7 +4,6 @@
4 4
 #include <stddef.h>
5 5
 #include <stdarg.h>
6 6
 
7
-unsigned int sleep ( unsigned int seconds );
8 7
 extern int execv ( const char *command, char * const argv[] );
9 8
 
10 9
 /**
@@ -22,10 +21,21 @@ extern int execv ( const char *command, char * const argv[] );
22 21
 		rc;							\
23 22
 	} )
24 23
 
25
-void udelay(unsigned int usecs);
26
-void mdelay(unsigned int msecs);
24
+/* Pick up udelay() */
25
+#include <gpxe/timer.h>
27 26
 
28
-#define usleep(x) udelay(x)
27
+/*
28
+ * sleep() prototype is defined by POSIX.1.  usleep() prototype is
29
+ * defined by 4.3BSD.  udelay() and mdelay() prototypes are chosen to
30
+ * be reasonably sensible.
31
+ *
32
+ */
33
+
34
+extern unsigned int sleep ( unsigned int seconds );
35
+extern void mdelay ( unsigned long msecs );
29 36
 
37
+static inline __always_inline void usleep ( unsigned long usecs ) {
38
+	udelay ( usecs );
39
+}
30 40
 
31 41
 #endif /* _UNISTD_H */

Loading…
Cancel
Save