Subject: bus_dmamem accessors.
To: None <tech-kern@netbsd.org>
From: Eduardo Horvath <eeh@turbolinux.com>
List: tech-kern
Date: 06/25/2000 09:10:25
DMA is used for two very different things.  It's used to move opaque cunks
of data in and out of main memory, and it is sometimes used to communicate
with devices through shared memory.  Our current setup works well for the
former but breaks down for the latter purpose since there is no way to
handle devices of different endianness.  This became most apparent when
trying to get the HME driver to work on but PCI and SBus.  SBus requires
big-endian data in memory, while PCI requires little-endian data.  This
information is available only to the bus-specific front end which needs to
export it to the main driver, and the main driver needs to test a value
and decide whether to swap on every access.

To help solve this problem I propose the following interfaces:


Two new flags will be added to bus_dmamap_create(), which will be used to tag
the bus_dmamap_t:

BUS_DMA_LITTLE_ENDIAN		The device expects data in little-endian
				format.
BUS_DMA_BIG_ENDIAN		The device expects data in big-endian
				format.

If neither flag is set then the device will only use opaque/streaming
access and endiannes is not important.  The bus_dmamem_map() call and
accessor functions can do whatever is most efficient on that architecture.  

In addition I propose a set of accessor routines which are to be used in
the same way as the bus_space* accessor routines when reading from or
writing to DMA memory to be used to communicate with a device.  The
routines can be either macros or functions, depending on the
implementation.

Here is a summary of those accessors:


     u_int16_t
     bus_dmamem_read_2(bus_dmamap_t map, caddr_t addr);

     u_int32_t
     bus_dmamem_read_4(bus_dmamap_t map, caddr_t addr;

     u_int64_t
     bus_dmamem_read_8(bus_dmamap_t map, caddr_t addr);

     void
     bus_dmamem_write_1(bus_dmamap_t map, caddr_t addr, u_int8_t value);

     void
     bus_dmamem_write_2(bus_dmamap_t map, caddr_t addr, u_int16_t value);

     void
     bus_dmamem_write_4(bus_dmamap_t map, caddr_t addr, u_int32_t value);

     void
     bus_dmamem_write_8(bus_dmamap_t map, caddr_t addr, u_int64_t value);

     void
     bus_dmamem_read_region_1(bus_dmamap_t map, caddr_t addr, 
	     u_int8_t *datap, unsigned long count);

     void
     bus_dmamem_read_region_2(bus_dmamap_t map, caddr_t addr, 
	     u_int16_t *datap, unsigned long count);

     void
     bus_dmamem_read_region_4(bus_dmamap_t map, caddr_t addr, 
	     u_int32_t *datap, unsigned long count);

     void
     bus_dmamem_read_region_8(bus_dmamap_t map, caddr_t addr, 
	     u_int64_t *datap, unsigned long count);

     void
     bus_dmamem_write_region_1(bus_dmamap_t map,
             caddr_t addr, u_int8_t *datap,
             unsigned long count);

     void
     bus_dmamem_write_region_2(bus_dmamap_t map,
             caddr_t addr, u_int16_t *datap,
             unsigned long count);

     void
     bus_dmamem_write_region_4(bus_dmamap_t map,
             caddr_t addr, u_int32_t *datap,
             unsigned long count);

     void
     bus_dmamem_write_region_8(bus_dmamap_t map,
             caddr_t addr, u_int64_t *datap,
             unsigned long count);

     void
     bus_dmamem_copy_region_1(bus_dmamap_t map,
             caddr_t srcaddr, caddr_t dstaddr,
             unsigned long count);

     void
     bus_dmamem_copy_region_2(bus_dmamap_t map,
             caddr_t srcaddr, caddr_t dstaddr,
             unsigned long count);

     void
     bus_dmamem_copy_region_4(bus_dmamap_t map,
             caddr_t srcaddr, caddr_t dstaddr,
             unsigned long count);

     void
     bus_dmamem_copy_region_8(bus_dmamap_t map,
             caddr_t srcaddr, caddr_t dstaddr,
             unsigned long count);

     void
     bus_dmamem_set_region_1(bus_dmamap_t map, caddr_t addr, 
	     u_int8_t value, unsigned long count);

     void
     bus_dmamem_set_region_2(bus_dmamap_t map, caddr_t addr, 
	     u_int16_t value, unsigned long count);

     void
     bus_dmamem_set_region_4(bus_dmamap_t map, caddr_t addr, 
	     u_int32_t value, unsigned long count);

     void
     bus_dmamem_set_region_8(bus_dmamap_t map, caddr_t addr, 
	     u_int64_t value, unsigned long count);

     void
     bus_dmamem_read_multi_1(bus_dmamap_t map, caddr_t addr,  
	     u_int8_t *datap, unsigned long count);

     void
     bus_dmamem_read_multi_2(bus_dmamap_t map, caddr_t addr,  
	     u_int16_t *datap, unsigned long count);

     void
     bus_dmamem_read_multi_4(bus_dmamap_t map, caddr_t addr,  
	     u_int32_t *datap, unsigned long count);

     void
     bus_dmamem_read_multi_8(bus_dmamap_t map, caddr_t addr,  
	     u_int64_t *datap, unsigned long count);

     void
     bus_dmamem_write_multi_1(bus_dmamap_t map, caddr_t addr,  
	     u_int8_t *datap, unsigned long count);

     void
     bus_dmamem_write_multi_2(bus_dmamap_t map, caddr_t addr,  
	     u_int16_t *datap, unsigned long count);

     void
     bus_dmamem_write_multi_4(bus_dmamap_t map, caddr_t addr,  
	     u_int32_t *datap, unsigned long count);

     void
     bus_dmamem_write_multi_8(bus_dmamap_t map, caddr_t addr,  
	     u_int64_t *datap, unsigned long count);



Eduardo Horvath