Subject: Re: DMA beyond end of isa
To: None <port-i386@NetBSD.ORG>
From: Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
List: port-i386
Date: 12/29/1995 10:12:45
Since there were some statements like "It's not in the tree because it's not
architecture independent" I would like to discuss the technical aspect of
my isadma/bounce buffer implementation. The sole reply from core was
"Please be patient, we'll get to it as soon as possible." dated Fri, Sep 29.

If this implementation is not architecture independent enough, please describe
this in more detail. I'm willing to spend more work on this problem if there
are pointers into the right directions.

The isadma/bounce buffer implementation based on NetBSD-current is available as

    ftp://bseis.eis.cs.tu-bs.de/pub/hannken/isadma-patch


My ISA/machine interface consists of 4 functions:

*)  int  isadma_map(caddr_t addr, vm_size_t nbytes,
		    struct isadma_seg *phys, int flags)

    Make a physical representation of the virtual memory region 'addr(size)'
    suitable for ISA dma. Result goes to 'phys', an array of

    struct isadma_seg {		/* a physical contiguous segment */
	vm_offset_t addr;	/* physical address of this segment */
	vm_size_t length;	/* length of this segment (bytes) */
    }

    'flags' controls the type of mapping/bouncing and is built of

    ISADMA_MAP_WAITOK	/* OK for isadma_map to sleep */
    ISADMA_MAP_BOUNCE	/* use bounce buffer if necessary */
    ISADMA_MAP_CONTIG	/* Result must be physically contiguous */
    ISADMA_MAP_8BIT	/* Result must not cross 64k boundary */
    ISADMA_MAP_16BIT	/* Result must not cross 128k boundary */

    The result is an array of physical segments. If ISADMA_MAP_CONTIG is set,
    the array contains just one segment (needed for on-board dma).

    If it is not possible to resolve the 'flags' the return value is zero.
    Otherwise it is the number of segments in 'phys'.

*)  void isadma_unmap (caddr_t addr, vm_size_t nbytes,
		       int nphys, struct isadma_seg *phys)

    Undo a mapping done by 'isadma_map'. This function MUST be called for
    every successfull mapping since the mapping may use resources that
    have to be freed.
    'nphys' is the return value from 'isadma_map'.

*)  void isadma_copytobuf (caddr_t addr, vm_size_t nbytes,
			   int nphys, struct isadma_seg *phys)

    This function copies data from the virtual to the physical memory.
    This may be a NOP if this is only a mapping but does a real copy
    if a bounce buffer is in use.

*)  void isadma_copyfrombuf (caddr_t addr, vm_size_t nbytes,
			     int nphys, struct isadma_seg *phys)

    This function copies data from the physical to the virtual memory.
    This may be a NOP if this is only a mapping but does a real copy
    if a bounce buffer is in use.


Using this interface 'isadma_start' (formerly 'isa_dmastart') looks roughly
like this

    isadma_map(addr, nbytes, &phys[chan], ISADMA_MAP_WAITOK |
	       ISADMA_MAP_BOUNCE | ISADMA_MAP_CONTIG | ISADMA_MAP_?BIT);
    if(write_to_device)
	isadma_copytobuf(addr, nbytes, 1, &phys[chan]);

The corresponding 'isadma_done' is

    if(read_from_device)
	isadma_copyfrombuf(addr, nbytes, 1, &phys[chan]);
    isadma_unmap(addr, nbytes, 1, &phys[chan]);

-- Juergen

--
Juergen Hannken-Illjes - hannken@eis.cs.tu-bs.de - TU Braunschweig (W Germany)