Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 Jul 1998 09:05:26 +0000 (GMT)
From:      Terry Lambert <tlambert@primenet.com>
To:        wpaul@skynet.ctr.columbia.edu (Bill Paul)
Cc:        current@FreeBSD.ORG
Subject:   Re: Device driver weirdness
Message-ID:  <199807110905.CAA16491@usr08.primenet.com>
In-Reply-To: <199807102354.TAA23827@skynet.ctr.columbia.edu> from "Bill Paul" at Jul 10, 98 07:54:08 pm

next in thread | previous in thread | raw e-mail | index | archive | help

> The macro basically reads back the command register after it's been
> written. This seems to defeat the cache and forces the interrupt
> acknowledgement to be written out.
> 
> What I don't understand is why I have to do this. I have declared
> the csr structure like this:

[ ... major use of "volatile" keyword ... ]

> I was under the impression that the volatile keyword was supposed to
> help avoid this problem, but even with 'volatile' in there I still need
> to use the macros to force the cache flush in order for commands to
> be written to the chip on time. I had the same problem with the code
> that read the EEPROM and used the same macro workaround, but I stupidly
> forgot the lesson I'd learned and didn't think I might have the same
> problem with the other registers.

The "volatile" keyword indicates something that might have changed
since the last time it was accessed, and thus should not be optimied
into a cached reference (ie: in a register) instead of a memory
reference.

In general, it refers to disabling the class of optimizations permitted
by ANSI C when assuming that there is a single program counter context
executing in a region of code, and that there will not be an async
escape to a seperate context, with a subsequent return to the original.


This is very different from affecting cached values that are cached inn
an L1 or L2 cache, not auto variables cached in a register.

To resolve this issue, you will need to mark the memory region
non-cacheable, and if you are running an older IBM or Cyrix processor
(pre the "Blue Lightning" chipmask), you will either need to disable
the CPU cache or explicitly call BINVD on the memory address range
in question after notification that the I/O has completed (since these
processors do not honor the "noncacheable" bit).


For your use, you will need to mark the memory in the ack region as
non-cacheable.  You can either mark all the memory non-cacheable, which
may impact performance if you reference it directly, multiple times,
from the driver, or you can butt a page up against the area and mark
the page prior as non-cacheable.

Most liely, you should explicitly call BINVD on the region in question,
or use the hack you are currently using to force the cache invalidation.


Since your current hack relies a bit on chip architecture (much like
BSD's DELAY() macro does), you should probably use BINVD to force the
flush of the cache contents (since the cache is write-through), or
disable the cache for the relevent page(s) -- or both, if you want it
to work with older processors.


There are write cache effects in the I/O address space as well, but
they can be defeated with read-after-write (see the Linux DELAY() macro,
and compare and contrast it to the FreeBSD version of the macro; this
is why some keyboards still lock up with FreeBSD console drivers when
LED changes are occurring).


					Terry Lambert
					terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



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