Subject: re: Using same com.c driver for two devices that access serial port differently?
To: Ignatios Souvatzis <is@netbsd.org>
From: matthew green <mrg@eterna.com.au>
List: tech-kern
Date: 06/26/2003 15:12:48
   
   On Wed, Jun 25, 2003 at 11:22:27PM +0000, Ian Zagorskih wrote:
   
   > ---cut ---
   > #define bus_space_read_1(t, h, o) \
   > 	((t) == I386_BUS_SPACE_IO ? (inb((h) + (o))) : \
   > 	((t) == MY_BUS_SPACE) ? (my_bus_read_1((t), (h), (o))) : \
   > 	((t) == YOUR_BUS_SPACE) ? (your_bus_read_1((t), (h), (o))) : \
   > 	((t) == HIS_BUS_SPACE) ? (his_bus_read_1((t), (h), (o))) : \
   >         (*(volatile u_int8_t *)((h) + (o))))
   > ---cut ---
   > 
   > but this dosn't seems to be good nor elegant for me. Or i missed something ?
   
   Use an array of function pointers for the access types, maybe, pointed to
   by the bus space tag. I don't know how bad this would be for i386
   performance; I had to do it this way for Amiga.
   
   The other solution - would be to rewrite com.c to take an array of offsets;
   this way only com.c would be penalized.


i think this comes down to a discussion that occured a year or so
ago[1] - for a similar issue.  to solve it properly, bus_space macros
need to be overridable on a per-bus driver basis, and as per-bus
drivers can be MI it really involves changing the definition of
<machine/bus.h>...  i recently had to solve a similar (it was
endianness rather than sparse addressing) on the sparc port and
my solution was to change the bus_space macro's into inline functions
that basically look like this:

	static __inline__ u_int8_t
	bus_space_read_1(t, h, o)
		bus_space_tag_t         t;
		bus_space_handle_t      h;
		bus_size_t              o;
	{
		return t->sparc_read_1 ?
			(*t->sparc_read_1)(t, h, o) :
			bus_space_read_1_real(t, h, o);
	}

where bus_space_read_1_real is defined as the previous version
(which is a simple direct accessor.)  this basically just turns
a direct access into a test and access in the normal case and
a function call in the special case.  expecting this to have a
slight but noticable effect i benchmarked this and i found that
the variance in my testing usually outweighed any negative
impact so far that often the "new should be slower" kernel was
faster more than not.  testing run on a sparc classic.


perhaps this is the way we should go for a truly "generic" bus
space that deal with these cases... i'm not sure.  i don't know
how expensive the memory accesses (probably two of them) and
the test are...


.mrg.


[1] - this was about creating a <sys/bus.h> ?  i forget...