Date: Mon, 30 Aug 2004 17:40:27 +0900 From: Pyun YongHyeon <yongari@kt-is.co.kr> To: sparc64@freebsd.org Subject: bus_dma_tag_create(9) broken? Message-ID: <20040830084027.GA1465@kt-is.co.kr>
next in thread | raw e-mail | index | archive | help
--YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-Disposition: inline While checking the possibility of "Trident 4D-Wave NX PCI" sound card on sparc64, I encountered an unexpected behavior from bus_dma(9). Since the audio card can't access address ranges larger than 1GB, I had to reduce possible DMA space with 0x3fffffff. But this generated an error in bus_dmamem_load(9) so the card couldn't get proper DMA-capable address. In i386, it seems that there is no such limitations at all. (Both BUS_SPACE_MAXADDR_24BIT, 0x3fffffff works OK.) Anyway the driver snd_t4dwave was broken since it failed to limit DMA addresses. I wonder how the driver worked on i386/amd64. In sparc64, is it intended behavior of bus_dma_tag_create(9)? If this is inherited feature from sparc64 H/W, the Trident audio card couldn't be supported at all. I guess other drivers that don't support 32bit DMA addressing such as maestro/maestro3 has the same issue too. The attached file is sample code I used. Regards, Pyun YongHyeon -- Pyun YongHyeon <http://www.kr.freebsd.org/~yongari> --YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=Makefile # .PATH: ${.CURDIR} KMOD= bus_alloc SRCS= bus_alloc_test.c .include <bsd.kmod.mk> --YZ5djTAD1cGYuMQK Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="bus_alloc_test.c" #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/module.h> #include <machine/bus.h> #define ALLOC_SIZE (16*1024) static int foo_alloc(void); static void foo_free(void); bus_dma_tag_t dmat = NULL; bus_dmamap_t dmamap = 0; char *vbuf = NULL; bus_addr_t pbuf = 0; static void call_back(void *arg, bus_dma_segment_t *segs, int nseg, int error) { if (error == 0) pbuf = segs[0].ds_addr; else pbuf = 0; } static int foo_alloc(void) { if (bus_dma_tag_create( NULL, 2, 0, /*BUS_SPACE_MAXADDR_32BIT,*/ 0x3fffffff, BUS_SPACE_MAXADDR, NULL, NULL, ALLOC_SIZE, 1, ALLOC_SIZE, BUS_DMA_ALLOCNOW, NULL, NULL, &dmat) != 0) { printf("unable to create dma tag\n"); return (-1); } if (bus_dmamem_alloc(dmat, (void **)&vbuf, BUS_DMA_NOWAIT, &dmamap)) { printf("bus_dmamem_alloc() fail\n"); foo_free(); } if (bus_dmamap_load(dmat, dmamap, vbuf, ALLOC_SIZE, call_back, NULL, 0)) { printf("bus_dmamap_load() fail\n"); foo_free(); } printf("pbuf = 0x%lx\n", pbuf); return (0); } static void foo_free(void) { if (dmamap) bus_dmamap_unload(dmat, dmamap); if (dmamap) bus_dmamem_free(dmat, vbuf, dmamap); if (dmat) bus_dma_tag_destroy(dmat); dmat = NULL; dmamap = 0; vbuf = NULL; pbuf = 0; } static int bus_modevent(module_t mod, int type, void *data) { int err = 0; switch(type) { case MOD_LOAD: foo_alloc(); break; case MOD_UNLOAD: foo_free(); break; default: err = EINVAL; break; } return (err); } static moduledata_t bus_alloc = { "bus_alloc", bus_modevent, 0 }; DECLARE_MODULE(bus_alloc, bus_alloc, SI_SUB_PSEUDO, SI_ORDER_FIRST); MODULE_VERSION(bus_alloc, 1); --YZ5djTAD1cGYuMQK--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040830084027.GA1465>