, Jason Thorpe <thorpej@nas.nasa.gov>
From: Matthias Drochner <drochner@zelux6.zel.kfa-juelich.de>
List: port-sparc
Date: 06/17/1997 15:33:13
Since the VME framework thread seems to trickle away again,
I'll throw in something constructive: a <sys/dev/vmevar.h>
which defines what I consider necessary for a generic VME
interface.
Not that I want to hard-sell my solution here, nor that I'm
desperately looking for more work... it's perhaps a starting point
and a base for discussion.
The DMA framework used here is not exactly Jason's, but
it's structure is similar (it's derived from an early draft).
I know that a limited kernel stack is an argument against too
much call nesting. This is perhaps a weakness in the layout
of the mapping functions here. I haven't a better idea which
still allows to pass the bus dependant parameters.
Comments?
best regards
Matthias
#ifndef _vmevar_h_
#define _vmevar_h_
typedef u_int32_t vme_addr_t, vme_size_t;
typedef int vme_am_t;
typedef enum {
VME_D8 = 1,
VME_D16 = 2,
VME_D32 = 4
} vme_datasize_t; /* can be or'ed to express multiple capabilities */
typedef int vme_swap_t; /* hardware swap capabilities,
contents to be specified */
#ifdef _KERNEL
/* generic placeholder for any ressources needed for a mapping,
overloaded by bus interface driver */
typedef void *vme_mapresc_t;
/*
* tag structure passed to VME bus devices,
* contains the bus dependant functions, accessed via macros below
*/
typedef struct vme_chipset_tag {
void *cookie;
int (*vct_map) __P((void*, vme_addr_t, vme_size_t,
vme_am_t, vme_datasize_t, vme_swap_t,
bus_space_tag_t*, bus_space_handle_t*,
vme_mapresc_t*));
void (*vct_unmap) __P((void*, vme_mapresc_t));
int (*vct_badaddr) __P((void*, bus_space_tag_t, bus_space_handle_t,
bus_size_t, vme_datasize_t));
void *(*vct_int_map) __P((void*, int, int,
int (*)(void*), void*));
void (*vct_int_unmap) __P((void*, void*));
int (*vct_dmamap_create) __P((void*, vme_size_t,
vme_am_t*, vme_datasize_t*, vme_swap_t*,
int, bus_dma_handle_t*));
void (*vct_dmamap_destroy) __P((void*, bus_dma_handle_t));
int (*vct_cntlrdmamap_create) __P((void*, vme_addr_t, vme_size_t,
vme_am_t, vme_datasize_t, vme_swap_t,
int, bus_cntlrdma_handle_t*));
void (*vct_cntlrdmamap_destroy) __P((void*, bus_cntlrdma_handle_t));
struct vmebus_softc *bus;
} *vme_chipset_tag_t;
/*
* map / unmap: map VME address ranges into kernel address space
* XXX should have mapping to CPU only to allow user mmap() without
* wasting kvm
*/
#define vme_space_map(vc, vmeaddr, len, am, datasize, swap, tag, handle,
resc) \
(*((vc)->vct_map))((vc)->cookie, (vmeaddr), (len), (am), (datasize), \
(swap), (tag), (handle), (resc))
#define vme_space_unmap(vc, resc) \
(*((vc)->vct_unmap))((vc)->cookie, (resc))
/*
* badaddr: check readability
*/
#define vme_badaddr(vc, tag, handle, offset, datasize) \
(*((vc)->vct_badaddr))((vc)->cookie, (tag), (handle), (offset), (datasize))
/*
* install / deinstall VME interrupt handler
*/
#define vme_intr_establish(vc, level, vector, func, arg) \
(*((vc)->vct_int_map))((vc)->cookie, \
(level), (vector), (func), (arg))
#define vme_intr_disestablish(vc, hdl) \
(*((vc)->vct_int_unmap))((vc)->cookie, (hdl))
/*
* create DMA handle (which is later used by bus independant
* DMA functions
*/
#define vme_dmamap_create(vc, size, am, datasize, swap, flags, handle) \
(*((vc)->vct_dmamap_create))((vc)->cookie, (size), (am), (datasize),
(swap), \
(flags), (handle))
#define vme_dmamap_destroy(vc, handle) \
(*((vc)->vct_dmamap_destroy))((vc)->cookie, (handle))
/*
* create handle for "controller DMA" or "data mover",
* later used by bus independant functions
*/
#define vme_cntlrdmamap_create(vc, vmeaddr, size, am, datasize, swap,
flags, handle) \
(*((vc)->vct_cntlrdmamap_create))((vc)->cookie, (vmeaddr), (size),
(am), (datasize), \
(swap), (flags), (handle))
#define vme_cntlrdmamap_destroy(vc, handle) \
(*((vc)->vct_cntlrdmamap_destroy))((vc)->cookie, (handle))
/*
* autoconfiguration data structures
*/
struct vmebus_attach_args{
vme_chipset_tag_t va_vct;
bus_dma_tag_t va_bdt;
bus_cntlrdma_tag_t va_bcdt;
bus_lock_tag_t va_bltt;
};
struct vmebus_softc{
struct device sc_dev;
vme_chipset_tag_t sc_vct;
bus_dma_tag_t sc_bdt;
bus_cntlrdma_tag_t sc_bcdt;
bus_lock_tag_t sc_bltt;
struct extent *vme32ext, *vme24ext, *vme16ext;
};
/* nr of addresses given in the kernel configuration file */
#define VME_NUMCFRANGES 3
struct vme_range {
vme_addr_t offset;
vme_size_t size;
vme_am_t am;
};
struct vme_attach_args{
struct vme_range r[VME_NUMCFRANGES];
int ivector, ilevel;
vme_chipset_tag_t va_vct;
bus_dma_tag_t va_bdt;
bus_cntlrdma_tag_t va_bcdt;
bus_lock_tag_t va_bltt;
};
/*
* address space accounting
*/
int _vme_space_alloc __P((struct vmebus_softc*, vme_addr_t, vme_size_t,
vme_am_t));
void _vme_space_free __P((struct vmebus_softc*, vme_addr_t, vme_size_t,
vme_am_t));
int _vme_space_get __P((struct vmebus_softc*, vme_size_t, vme_am_t,
u_long, vme_addr_t*));
#define vme_space_alloc(tag, addr, size, ams) \
_vme_space_alloc(tag->bus, addr, size, ams)
#define vme_space_free(tag, addr, size, ams) \
_vme_space_free(tag->bus, addr, size, ams)
#define vme_space_get(tag, size, ams, align, addr) \
_vme_space_get(tag->bus, size, ams, align, addr)
#endif /* KERNEL */
#endif /* _vmevar_h_ */