micro_delay in sysutil, used in ti1225, dp8390, fxp and
orinoco now. Uses a combination of tickdelay (where possible) and calibrated busywait (where necessary).
This commit is contained in:
parent
2dc2db4ba1
commit
03446f5554
@ -22,8 +22,6 @@ Created: April 2000 by Philip Homburg <philip@f-mnx.phicoh.com>
|
|||||||
|
|
||||||
#if ENABLE_PCI
|
#if ENABLE_PCI
|
||||||
|
|
||||||
#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
|
|
||||||
|
|
||||||
PRIVATE struct pcitab
|
PRIVATE struct pcitab
|
||||||
{
|
{
|
||||||
u16_t vid;
|
u16_t vid;
|
||||||
@ -43,7 +41,6 @@ _PROTOTYPE( static void ee_wen, (dpeth_t *dep) );
|
|||||||
_PROTOTYPE( static void set_ee_word, (dpeth_t *dep, int a, U16_t w) );
|
_PROTOTYPE( static void set_ee_word, (dpeth_t *dep, int a, U16_t w) );
|
||||||
_PROTOTYPE( static void ee_wds, (dpeth_t *dep) );
|
_PROTOTYPE( static void ee_wds, (dpeth_t *dep) );
|
||||||
#endif
|
#endif
|
||||||
_PROTOTYPE( static void micro_delay, (unsigned long usecs) );
|
|
||||||
|
|
||||||
PUBLIC int rtl_probe(dep)
|
PUBLIC int rtl_probe(dep)
|
||||||
struct dpeth *dep;
|
struct dpeth *dep;
|
||||||
@ -373,11 +370,6 @@ dpeth_t *dep;
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void micro_delay(unsigned long usecs)
|
|
||||||
{
|
|
||||||
tickdelay(MICROS_TO_TICKS(usecs));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ENABLE_PCI */
|
#endif /* ENABLE_PCI */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -112,13 +112,9 @@ typedef int irq_hook_t;
|
|||||||
#define structof(type, field, ptr) \
|
#define structof(type, field, ptr) \
|
||||||
((type *) (((char *) (ptr)) - offsetof(type, field)))
|
((type *) (((char *) (ptr)) - offsetof(type, field)))
|
||||||
|
|
||||||
#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
|
|
||||||
|
|
||||||
static timer_t *fxp_timers= NULL;
|
static timer_t *fxp_timers= NULL;
|
||||||
static clock_t fxp_next_timeout= 0;
|
static clock_t fxp_next_timeout= 0;
|
||||||
|
|
||||||
static void micro_delay(unsigned long usecs);
|
|
||||||
|
|
||||||
/* ignore interrupt for the moment */
|
/* ignore interrupt for the moment */
|
||||||
#define interrupt(x) 0
|
#define interrupt(x) 0
|
||||||
|
|
||||||
@ -295,6 +291,9 @@ int main(int argc, char *argv[])
|
|||||||
fxp_init_buf(fp);
|
fxp_init_buf(fp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if((r=micro_delay_calibrate()) != OK)
|
||||||
|
panic("FXP","rmicro_delay_calibrate failed", r);
|
||||||
|
|
||||||
/* Try to notify inet that we are present (again) */
|
/* Try to notify inet that we are present (again) */
|
||||||
r= ds_retrieve_u32("inet", &tasknr);
|
r= ds_retrieve_u32("inet", &tasknr);
|
||||||
if (r == OK)
|
if (r == OK)
|
||||||
@ -2875,11 +2874,6 @@ PRIVATE void fxp_expire_timers()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void micro_delay(unsigned long usecs)
|
|
||||||
{
|
|
||||||
tickdelay(MICROS_TO_TICKS(usecs));
|
|
||||||
}
|
|
||||||
|
|
||||||
static u8_t do_inb(port_t port)
|
static u8_t do_inb(port_t port)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
@ -46,24 +46,6 @@ int this_proc;
|
|||||||
|
|
||||||
#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
|
#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* milli_delay *
|
|
||||||
* *
|
|
||||||
* Wait usecs micro seconds. Clearly needs revision *
|
|
||||||
*****************************************************************************/
|
|
||||||
static void micro_delay(unsigned long usecs)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
if(usecs >= 100) {
|
|
||||||
/* If the delay is long, we might as well use ticks */
|
|
||||||
tickdelay(MICROS_TO_TICKS(usecs));
|
|
||||||
} else {
|
|
||||||
/* use another type of hack :-), or a proper implementation */
|
|
||||||
for(i=0; i < 1000 * usecs; i++){j+=1;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* milli_delay *
|
* milli_delay *
|
||||||
* *
|
* *
|
||||||
|
@ -14,8 +14,6 @@ Created: Dec 2005 by Philip Homburg
|
|||||||
/* The use of interrupts is not yet ready for prime time */
|
/* The use of interrupts is not yet ready for prime time */
|
||||||
#define USE_INTS 0
|
#define USE_INTS 0
|
||||||
|
|
||||||
#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
|
|
||||||
|
|
||||||
#define NR_PORTS 2
|
#define NR_PORTS 2
|
||||||
|
|
||||||
PRIVATE struct port
|
PRIVATE struct port
|
||||||
@ -59,7 +57,6 @@ FORWARD _PROTOTYPE( void do_int, (struct port *pp) );
|
|||||||
FORWARD _PROTOTYPE( u8_t read_exca, (struct port *pp, int socket, int reg) );
|
FORWARD _PROTOTYPE( u8_t read_exca, (struct port *pp, int socket, int reg) );
|
||||||
FORWARD _PROTOTYPE( void do_outb, (port_t port, u8_t value) );
|
FORWARD _PROTOTYPE( void do_outb, (port_t port, u8_t value) );
|
||||||
FORWARD _PROTOTYPE( u8_t do_inb, (port_t port) );
|
FORWARD _PROTOTYPE( u8_t do_inb, (port_t port) );
|
||||||
FORWARD _PROTOTYPE( void micro_delay, (unsigned long usecs) );
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -68,6 +65,9 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
|
(progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
|
||||||
|
|
||||||
|
if((r=micro_delay_calibrate()) != OK)
|
||||||
|
panic("ti1225", "micro_delay_calibrate failed", r);
|
||||||
|
|
||||||
debug= 0;
|
debug= 0;
|
||||||
while (c= getopt(argc, argv, "d?"), c != -1)
|
while (c= getopt(argc, argv, "d?"), c != -1)
|
||||||
{
|
{
|
||||||
@ -492,8 +492,4 @@ PRIVATE void do_outb(port_t port, u8_t value)
|
|||||||
panic("ti1225","sys_outb failed", r);
|
panic("ti1225","sys_outb failed", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE void micro_delay(unsigned long usecs)
|
|
||||||
{
|
|
||||||
tickdelay(MICROS_TO_TICKS(usecs));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -65,8 +65,6 @@ int aux_irq_hook_id = -1;
|
|||||||
* keyboard.
|
* keyboard.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
|
|
||||||
|
|
||||||
#define CONSOLE 0 /* line number for console */
|
#define CONSOLE 0 /* line number for console */
|
||||||
#define KB_IN_BYTES 32 /* size of keyboard input buffer */
|
#define KB_IN_BYTES 32 /* size of keyboard input buffer */
|
||||||
PRIVATE char ibuf[KB_IN_BYTES]; /* input buffer */
|
PRIVATE char ibuf[KB_IN_BYTES]; /* input buffer */
|
||||||
@ -153,7 +151,6 @@ FORWARD _PROTOTYPE( void set_leds, (void) );
|
|||||||
FORWARD _PROTOTYPE( void show_key_mappings, (void) );
|
FORWARD _PROTOTYPE( void show_key_mappings, (void) );
|
||||||
FORWARD _PROTOTYPE( int kb_read, (struct tty *tp, int try) );
|
FORWARD _PROTOTYPE( int kb_read, (struct tty *tp, int try) );
|
||||||
FORWARD _PROTOTYPE( unsigned map_key, (int scode) );
|
FORWARD _PROTOTYPE( unsigned map_key, (int scode) );
|
||||||
FORWARD _PROTOTYPE( void micro_delay, (unsigned long usecs) );
|
|
||||||
FORWARD _PROTOTYPE( void kbd_watchdog, (timer_t *tmrp) );
|
FORWARD _PROTOTYPE( void kbd_watchdog, (timer_t *tmrp) );
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
@ -1263,9 +1260,10 @@ int *isauxp;
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void micro_delay(unsigned long usecs)
|
int micro_delay(u32_t usecs)
|
||||||
{
|
{
|
||||||
tickdelay(MICROS_TO_TICKS(usecs));
|
tickdelay(MICROS_TO_TICKS(usecs));
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef _EXTRALIB_H
|
#ifndef _MINIX_SYSUTIL_H
|
||||||
#define _EXTRALIB_H
|
#define _MINIX_SYSUTIL_H 1
|
||||||
|
|
||||||
/* Extra system library definitions to support device drivers and servers.
|
/* Extra system library definitions to support device drivers and servers.
|
||||||
*
|
*
|
||||||
@ -46,6 +46,10 @@ _PROTOTYPE( void report, (char *who, char *mess, int num));
|
|||||||
_PROTOTYPE( void panic, (char *who, char *mess, int num));
|
_PROTOTYPE( void panic, (char *who, char *mess, int num));
|
||||||
_PROTOTYPE( int getuptime, (clock_t *ticks));
|
_PROTOTYPE( int getuptime, (clock_t *ticks));
|
||||||
_PROTOTYPE( int tickdelay, (clock_t ticks));
|
_PROTOTYPE( int tickdelay, (clock_t ticks));
|
||||||
|
_PROTOTYPE( int micro_delay_calibrate, (void));
|
||||||
|
_PROTOTYPE( int micro_delay, (u32_t micros));
|
||||||
|
|
||||||
#endif /* _EXTRALIB_H */
|
#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
|
||||||
|
|
||||||
|
#endif /* _MINIX_SYSUTIL_H */
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ libsysutil_FILES=" \
|
|||||||
env_panic.c \
|
env_panic.c \
|
||||||
env_prefix.c \
|
env_prefix.c \
|
||||||
fkey_ctl.c \
|
fkey_ctl.c \
|
||||||
|
micro_delay.c \
|
||||||
report.c \
|
report.c \
|
||||||
taskcall.c \
|
taskcall.c \
|
||||||
read_tsc.s \
|
read_tsc.s \
|
||||||
|
89
lib/sysutil/micro_delay.c
Normal file
89
lib/sysutil/micro_delay.c
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/times.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <minix/u64.h>
|
||||||
|
#include <minix/config.h>
|
||||||
|
#include <minix/const.h>
|
||||||
|
|
||||||
|
#include "sysutil.h"
|
||||||
|
|
||||||
|
#define CALIBRATE_TICKS (HZ/5)
|
||||||
|
#define MICROHZ 1000000 /* number of micros per second */
|
||||||
|
#define MICROSPERTICK (MICROHZ/HZ) /* number of micros per HZ tick */
|
||||||
|
|
||||||
|
static u32_t calib_tsc;
|
||||||
|
static int calibrated = 0;
|
||||||
|
|
||||||
|
int
|
||||||
|
micro_delay_calibrate(void)
|
||||||
|
{
|
||||||
|
u64_t start, end, diff, hz;
|
||||||
|
struct tms tms;
|
||||||
|
unsigned long t = 0;
|
||||||
|
|
||||||
|
/* Wait for clock to tick. */
|
||||||
|
while(!t || (t == times(&tms)))
|
||||||
|
t = times(&tms);
|
||||||
|
|
||||||
|
t++;
|
||||||
|
|
||||||
|
/* Wait for clock to tick CALIBRATE_TICKS times, and time
|
||||||
|
* this using the TSC.
|
||||||
|
*/
|
||||||
|
read_tsc_64(&start);
|
||||||
|
while(times(&tms) < t+CALIBRATE_TICKS) ;
|
||||||
|
read_tsc_64(&end);
|
||||||
|
|
||||||
|
diff = sub64(end, start);
|
||||||
|
if(ex64hi(diff) != 0)
|
||||||
|
panic(__FILE__,
|
||||||
|
"micro_delay_calibrate: CALIBRATE_TICKS too high "
|
||||||
|
"for TSC frequency\n", NO_NUM);
|
||||||
|
calib_tsc = ex64lo(diff);
|
||||||
|
printf("micro_delay_calibrate: "
|
||||||
|
"%lu cycles/%d ticks of %d Hz; %lu cycles/s\n",
|
||||||
|
calib_tsc, CALIBRATE_TICKS, HZ,
|
||||||
|
div64u(mul64u(calib_tsc, HZ), CALIBRATE_TICKS));
|
||||||
|
calibrated = 1;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
micro_delay(u32_t micros)
|
||||||
|
{
|
||||||
|
u64_t now, end;
|
||||||
|
|
||||||
|
/* Start of delay. */
|
||||||
|
read_tsc_64(&now);
|
||||||
|
|
||||||
|
/* We have to be calibrated. */
|
||||||
|
if(!calibrated) {
|
||||||
|
int r;
|
||||||
|
printf("micro_delay: calibrating\n");
|
||||||
|
if((r=micro_delay_calibrate()) != OK)
|
||||||
|
panic(__FILE__, "micro_delay: calibrate failed\n", r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have to know when to end the delay. */
|
||||||
|
end = add64u(now, div64u(mul64u(calib_tsc,
|
||||||
|
micros * HZ / CALIBRATE_TICKS), MICROHZ));
|
||||||
|
|
||||||
|
/* If we have to wait for at least one HZ tick, use the regular
|
||||||
|
* tickdelay first. Round downwards on purpose, so the average
|
||||||
|
* half-tick we wait short (depending on where in the current tick
|
||||||
|
* we call tickdelay). We can correct for both overhead of tickdelay
|
||||||
|
* itself and the short wait in the busywait later.
|
||||||
|
*/
|
||||||
|
if(micros >= MICROSPERTICK)
|
||||||
|
tickdelay(micros*HZ/MICROHZ);
|
||||||
|
|
||||||
|
/* Wait (the rest) of the delay time using busywait. */
|
||||||
|
while(cmp64(now, end) < 0)
|
||||||
|
read_tsc_64(&now);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user