Date: Tue, 11 Mar 1997 15:27:30 +0100 (MET) From: Emmanuel Duros <eduros@chouette.inria.fr> To: freebsd-hackers@freebsd.org Subject: Pb using DMA - Physical addressing Message-ID: <199703111427.PAA05582@chouette.inria.fr>
next in thread | raw e-mail | index | archive | help
Hi,
I am currently writing a device driver (isa bus) for a communication
card (satellite reception/emission cards) that uses DMA transfers.
I have got a peace of code that works fine under DOS but as I insert it
into the freebsd device driver code nothing happens.
I think the problem comes from the mapping of virtual addresses into
physical addresses (?). Unfortunately I have not found much
documentation on this...
Here is the simple C code for dos:
------- DOS
/*
* transfers a 188 byte buffer from
* memory to the device using drq 6
*/
u_char buf[188];
u_long addr;
u_char lsb, msb, page, lcnt, hcnt;
dma_ch = 6;
addr = ((unsigned long)FP_SEG ( buf ) << 4) /* get physical address */
+ FP_OFF ( buf );
lsb = (u_char)(addr >> 1);
msb = (u_char)(addr >> 9);
page = (u_char)(addr >> 16);
sz_dma = 188/2 - 1;
lcnt = sz_bma; hcnt = sz_dma >> 8;
_disable();
outp (SNGL_MASK_reg( dma_ch ) , DISABLE( dma_ch ));
/* DMA_MODE = BLOCK|ADDR_INC|AUTO_DISABLE|READ|(dma_ch-4) */
outp (MODE_reg( dma_ch ) , DMA_MODE);
outp (CLR_BYTE_PTR_reg( dma_ch ) , 0);
outp (BASE_ADDR_reg( dma_ch ) , lsb);
outp (BASE_ADDR_reg( dma_ch ) , msb);
outp (PAGE_ADDR_reg( dma_ch ) , page);
outp (CLR_BYTE_PTR_reg( dma_ch ) , 0);
outp (COUNT_reg( dma_ch ) , lcnt);
outp (COUNT_reg(dma_ch ) , hcnt);
_enable();
outp (SNGL_MASK_reg( dma_ch ), ENABLE( dma_ch ));
outp (SNGL_MASK_reg( dma_ch ), DISABLE( dma_ch ));
--------
Now is the very similare peace of code I wrote for the FreeBSD driver:
-------- FreeBSD
/*
* transfers a 188 byte buffer from
* memory to the device using drq 6
*/
buf = malloc( 188, M_DEVBUF, M_NOWAIT); /* this is from the attach function */
/* am I sure that buf < 16M ??? */
/* filling buffer here */
addr = pmap_extract(pmap_kernel(), (vm_offset_t) buf);
/* I found this function, but not quite sure of its behavior)
/* or addr = (u_int) buf; ??? */
lsb = (u_char)(addr >> 1);
msb = (u_char)(addr >> 9);
page = (u_char)(addr >> 16 & 0xFE);
sz_dma = 188/2 - 1;
lcnt = sz_dma; hcnt = sz_dma >> 8;
outb (SNGL_MASK_reg( dma_ch ) , DISABLE( dma_ch ));
outb (MODE_reg( dma_ch ) , DMA_MODE);
outb (CLR_BYTE_PTR_reg( dma_ch ), 0);
outb (BASE_ADDR_reg( dma_ch ) , lsb);
outb (BASE_ADDR_reg( dma_ch ) , msb);
outb (PAGE_ADDR_reg( dma_ch ) , page);
outb (CLR_BYTE_PTR_reg( dma_ch ), 0);
outb (COUNT_reg( dma_ch ) , lcnt);
outb (COUNT_reg( dma_ch ) , hcnt);
outb (SNGL_MASK_reg( dma_ch ), ENABLE( dma_ch ));
outb (SNGL_MASK_reg( dma_ch ), DISABLE( dma_ch ));
--------
I think I do not give the DMA the correct address of buf, how can this
be done ?
If someone had any ideas on the problem, I would be very glad to hear
them !
Could anybody explain the relation between physical addressing and
virtual addressing ?
One last question, is it possible to develop in the user space
applications that would handle dma transfers ? In fact, I am a bit fed
up with rebooting my PC every time I recompile the kernel !
Thanks for your help...
Emmanuel
+--------------------------------------------------------------------+
|Emmanuel Duros | Emmanuel.Duros@sophia.inria.fr|
|INRIA Sophia Antipolis | Projet RODEO |
|2004, Route des Lucioles BP 93 | Phone : +33 04 93 65 79 42 |
|06902 Sophia Antipolis CEDEX France | Fax : +33 04 93 65 77 65 |
+--------------------------------------------------------------------+
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199703111427.PAA05582>
