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>
