[comp.unix.questions] Delay with no real time clock

jeffrey@masscomp.UUCP (Jeff Jones) (10/15/87)

I am working with a driver that must wait for a specified period of
time (usually less than one second) after issuing a command before
assuming that a device is not present.  This must happend during
device initialization time.

There are no real time clock interrupts during the device initialization
phase of our kernel.  The system time counter (lbolt in our case) does
not get incremented HZ times per second until after all devices
are initialized.  So, 

	How do you determine how much time has expired
	when you have no real time clock interrupt?

One would suppose the answer would be to set up a loop with a specific
number of instructions and then have some macro that tells you how
many of these loops occur per second.  But that would entail changing
the macro everytime you change the clock rate of the processor
(or changing the contents of the loop).  This is also somewhat
non-deterministic due the fact that the loop may or may not be in
an instruction cache.

I am curious to find our how others have dealt with this problem.

Thanx,
jeff jones

chris@mimsy.UUCP (Chris Torek) (10/16/87)

In article <2414@masscomp.UUCP> jeffrey@masscomp.UUCP (Jeff Jones) writes:
>I am working with a driver that must wait ... after issuing a command
>before assuming that a device is not present.  This must happend during
>device initialization time. ... There are no real time clock interrupts
>during the device initialization phase of our kernel.
>	How do you determine how much time has expired
>	when you have no real time clock interrupt?

My UDA50 driver has the same problem.  On Vaxen, there is a CPU
register called TODR (Time Of Day Register) that is incremented
once every millisecond, so to wait for one second, one could use

	register int timo = mfpr(TODR) + 1000;

	while ((device->status & READY) == 0)
		if (mfpr(TODR) >= timo)
			return (0);	/* device never went ready */

Alas, not *all* Vaxen have a TODR---in particular, the Microvax
series and (I believe) the 8800.  For now, I changed mfpr(TODR)
to a call to todr():

	register int timo = todr() + 1000;

	while ((device->status & READY) == 0)
		if (todr() >= timo)
			return (0);

The routine todr() then reads (approximately)

	todr()
	{
		switch (cpu) {

		case VAX_8600:
		case VAX_8200:
		case VAX_780:
		case VAX_750:
		case VAX_730:
			return (mfpr(TODR));

		case VAX_630:
			/* hack */
			{ static int t; DELAY(10000); return (++t); }
	}

It is sort of a hack, but it works.  Since it is used only at boot
time, it need not be very accurate---and it is better than having
the machine hang if a device gets stuck.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

boykin@custom.UUCP (Joseph Boykin) (10/16/87)

In article <2414@masscomp.UUCP>, jeffrey@masscomp.UUCP (Jeff Jones) writes:
> I am working with a driver that must wait for a specified period of
> time (usually less than one second) after issuing a command before
> assuming that a device is not present.  This must happend during
> device initialization time.
> 
> There are no real time clock interrupts during the device initialization
> phase of our kernel.  The system time counter (lbolt in our case) does
> not get incremented HZ times per second until after all devices
> are initialized.  So, 
> 
> 	How do you determine how much time has expired
> 	when you have no real time clock interrupt?

There are two solutions which I've used.  One has the advantage
that you don't have to do anything, the other means you might
have to do a little patching after the kernel is built.

1) Since you're doing this at initialization time and hence
not overly concerned about real-time performance, and
since the timeout is relatively short, I would just
wait long enough for your 'best' CPU performance.  If you're
running a 10MHz 68000 vs. a 25MHz 68020 with cache the same code
for the 68K will timeout in, say, 3 seconds instead of 0.5.
Not great, but not a disaster either.

2) Just as you patch the kernel once to change the 'uname' structure
to whatever name you want your system to have, add another location
(or struction) which has whatever other info you might find useful.
I've including things such as clock rate, CPU type, Kernel virtual
offset, plus any other tunable parameters I thought would be
of use.
-- 

Joe Boykin
Custom Software Systems
...necntc!custom!boykin

rneitzel@udenva.cair.du.edu (RICHARD NEITZEL ) (10/27/87)

In article <2414@masscomp.UUCP> jeffrey@masscomp.UUCP (Jeff Jones) writes:
>I am working with a driver that must wait for a specified period of
>time (usually less than one second) after issuing a command before
>assuming that a device is not present.  This must happend during
>device initialization time.
>
>There are no real time clock interrupts during the device initialization
>phase of our kernel.  The system time counter (lbolt in our case) does
>not get incremented HZ times per second until after all devices
>are initialized.  So, 
>
>	How do you determine how much time has expired
>	when you have no real time clock interrupt?
>
Well, if you have a clock board in the system that you can use to count down
times you can load the desired time into the clock board and then loop on its
done bit. This assumes that the board has a done bit of course. I have used this
for DEC's KWV11-C and I am sure that similar boards are available for other 
buses. The nice thing about this method is that you need only one clock board,
since you can use the board under interrupt control later.



				Rich Neitzel
			"Any job not worth doing is not worth doing well."
			"Make people think they think and they will love you;
			 make them think and they will hate you."