Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Feb 1997 21:42:49 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        brian@awfulhak.demon.co.uk, hackers@freebsd.org
Cc:        brian@utell.co.uk
Subject:   Re: Screen flickering
Message-ID:  <199702201042.VAA30639@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>Essentially, the syscons screen "flickers" probably every couple of
>seconds on average, and only with "vidcontrol -c destructive".  From
>what I can figure, the "while (!(inb(crtc_addr+6)&8)) ;" bit in
>syscons.c doesn't work as expected (although removing it makes
>things a *lot* worse)....

The timing is sometimes interfered with by interrupts.

The hardware is designed to be polled as follows:

	1. Disable CPU interrupts.  Don't worry about losing several
	   thousand serial interrupts while interrupts are disabled.
	2. Loop until the retrace bit is not set.
	3. Loop until the retrace bit is set.  Since interrupts are
	   disabled, the previous test of the retrace bit was done
	   less than 5 usec ago.  Since the bit was previously not
	   set, the video retrace must have begun less than 5 usec
	   ago.  Thus there is almost a full retrace period available
	   for step 4.
	4. Program the `sparkly' registers.
	5. Enable interrupts.

Disabling interrupts for a long time is unacceptable for a multitasking
OS.  The problem can be handled "right" if the video card can generate
vertical retrace interrupts:

	1. Make the vertical retrace interrupt handler a "fast" interrupt
	   handler so that it has a low latency and can't be interrupted.
	   Don't use too many other "fast" interrupt handlers, or the
	   interrupt latency might be too high.
	2. Program the sparkly registers in the vertical retrace interrupt
	   handler.  Do this in less than 20 usec or someone will complain
	   that the interrupt latency is too high.

Otherwise, the best that can be done is probably something like:

	1. Loop until the retrace bit is not set, recording the current
	   interrupt count before each test.
	2. Loop until the retrace bit is set, recording the current
	   interrupt from before each test whenever the loop continues.
	3. Disable interrupts.
	4. If the current interrupt count is different from the one
	   before the test that found the retrace bit not set, then
	   we must have been interrupted.  Enable interrupts and go to
	   step 1 in this case.
	5. Program the `sparkly' registers.  Do this in less than 20
	   usec or someone will complain that the interrupt latency is
	   too high.
	6. Enable interrupts.

Busy-waiting for a long time like this (average almost 1/70 seconds)
is also unacceptable for a multitasking OS.  This method also takes a
lot of code.  It can probably be improved at the cost of even more code
by recording timestamps instead of interrupt counts.  Then it could tell
that it was only interrupted for 50 usec (say), so there must be plenty of
time before the retrace completes, so the "go to step 1" step is unnecessary.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199702201042.VAA30639>