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

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
  */
13
 
13
 
14
 #include <stddef.h>
14
 #include <stddef.h>
15
-#include <bits/timer2.h>
16
-#include <gpxe/timer.h>
15
+#include <gpxe/timer2.h>
17
 #include <gpxe/io.h>
16
 #include <gpxe/io.h>
18
 
17
 
19
 /* Timers tick over at this rate */
18
 /* Timers tick over at this rate */
20
-#define TIMER2_TICK_RATE	1193180U
19
+#define TIMER2_TICKS_PER_SEC	1193180U
21
 
20
 
22
 /* Parallel Peripheral Controller Port B */
21
 /* Parallel Peripheral Controller Port B */
23
 #define	PPC_PORTB	0x61
22
 #define	PPC_PORTB	0x61
52
 #define	BINARY_COUNT	0x00
51
 #define	BINARY_COUNT	0x00
53
 #define	BCD_COUNT	0x01
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
 	 * Now let's take care of PPC channel 2
56
 	 * Now let's take care of PPC channel 2
59
 	 *
57
 	 *
75
 	outb(ticks >> 8, TIMER2_PORT);
73
 	outb(ticks >> 8, TIMER2_PORT);
76
 }
74
 }
77
 
75
 
78
-static int timer2_running(void)
79
-{
76
+static int timer2_running ( void ) {
80
 	return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
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
-/*
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
-
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
 #define BDA_FBMS 0x0013
5
 #define BDA_FBMS 0x0013
6
 #define BDA_NUM_DRIVES 0x0075
6
 #define BDA_NUM_DRIVES 0x0075
7
 
7
 
8
-extern unsigned long currticks ( void );
9
 extern void cpu_nap ( void );
8
 extern void cpu_nap ( void );
10
 
9
 
11
 #endif /* BIOS_H */
10
 #endif /* BIOS_H */

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

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
-#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

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

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

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

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
 
9
 
10
 #define IOAPI_X86
10
 #define IOAPI_X86
11
 #define PCIAPI_PCBIOS
11
 #define PCIAPI_PCBIOS
12
+#define TIMER_PCBIOS
12
 #define CONSOLE_PCBIOS
13
 #define CONSOLE_PCBIOS
13
 
14
 
14
 #endif /* CONFIG_DEFAULTS_PCBIOS_H */
15
 #endif /* CONFIG_DEFAULTS_PCBIOS_H */

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

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
 int monojob_wait ( const char *string ) {
63
 int monojob_wait ( const char *string ) {
64
 	int key;
64
 	int key;
65
 	int rc;
65
 	int rc;
66
-	tick_t last_progress_dot;
66
+	unsigned long last_progress_dot;
67
+	unsigned long elapsed;
67
 
68
 
68
 	printf ( "%s.", string );
69
 	printf ( "%s.", string );
69
 	monojob_rc = -EINPROGRESS;
70
 	monojob_rc = -EINPROGRESS;
81
 				break;
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
 			printf ( "." );
87
 			printf ( "." );
86
 			last_progress_dot = currticks();
88
 			last_progress_dot = currticks();
87
 		}
89
 		}

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

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
  * This program is free software; you can redistribute it and/or
4
  * This program is free software; you can redistribute it and/or
7
  * modify it under the terms of the GNU General Public License as
5
  * modify it under the terms of the GNU General Public License as
18
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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
 	while ( msecs-- )
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
 unsigned int sleep ( unsigned int secs ) {
36
 unsigned int sleep ( unsigned int secs ) {
110
 	while ( secs-- )
37
 	while ( secs-- )
111
-		mdelay ( MSECS_IN_SEC );
38
+		mdelay ( 1000 );
112
 	return 0;
39
 	return 0;
113
 }
40
 }

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

497
 
497
 
498
     unsigned char status;
498
     unsigned char status;
499
     unsigned i, retries;
499
     unsigned i, retries;
500
-    tick_t ct;
500
+    unsigned long ct;
501
 
501
 
502
     for (retries=0; retries < XMIT_RETRIES ; retries++)
502
     for (retries=0; retries < XMIT_RETRIES ; retries++)
503
 	{
503
 	{
543
 	ct = currticks();
543
 	ct = currticks();
544
 
544
 
545
 	while (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004) &&
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
 	if (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004))
549
 	if (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004))

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

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

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

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

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

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

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

112
 
112
 
113
 /* Operational parameters that usually are not changed. */
113
 /* Operational parameters that usually are not changed. */
114
 /* Time in jiffies before concluding the transmitter is hung. */
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
 #define PKT_BUF_SZ  1536  /* Size of each temporary Rx buffer.*/
117
 #define PKT_BUF_SZ  1536  /* Size of each temporary Rx buffer.*/
118
 
118
 
486
     /* send the packet to destination */
486
     /* send the packet to destination */
487
     unsigned entry;
487
     unsigned entry;
488
     int transmit_status;
488
     int transmit_status;
489
-    tick_t ct;
489
+    unsigned long ct;
490
 
490
 
491
     /* Caution: the write order is important here, set the field
491
     /* Caution: the write order is important here, set the field
492
        with the "ownership" bits last. */
492
        with the "ownership" bits last. */

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

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
 #include <stddef.h>
4
 #include <stddef.h>
5
 #include <stdarg.h>
5
 #include <stdarg.h>
6
 
6
 
7
-unsigned int sleep ( unsigned int seconds );
8
 extern int execv ( const char *command, char * const argv[] );
7
 extern int execv ( const char *command, char * const argv[] );
9
 
8
 
10
 /**
9
 /**
22
 		rc;							\
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
 #endif /* _UNISTD_H */
41
 #endif /* _UNISTD_H */

Loading…
Cancel
Save