Tomasz Motylewski wrote:
>
> On Thu, 27 Jul 2000, daniel sheltraw wrote:
>
> > > > (1) set up shared memory between RT module and user-space suitable
> > > > for DMA (contiguous memory),
> > >If you are talking ISA, you can't do what you want as far as shared
> > >memory, but I can
> > >help you with code.
>
> Hey, why not shared memory? Any memory block once allocated can be remapped
> in user space (if it starts and ends on page boundary). The only problem with
> ISA DMA it to actually GET unfragmented block of 32-64 KB size below 16 MB.
> If you press Shift-ScrollLock you will see the statistics of available blocks
> (run dmesg after)
Well, really, I know under certain situations you can used shared memory
and
DMA using ISA, but 32-64Kb is 1-2 seconds, and that's not much. Might
as well use
smaller blocks of DMA'able memory, pass the data back and forth using
shared memory
and keep loading the dma memory as required, such as through a DMA
interrupt. So i wasn't saying he can't use shared memory, i was just
saying that the easiest way will not be working on every machine. The
other thing about using DMA on a circular ring of smaller buffers is
that coordination between RT/NonRT and hardware is already handled.
I don't know what Daniel is up to, but say you want to have 24 tracks of
audio for recording a song. Then you probably need 100-200meg of ram
just to hold it in memory. A practical
program is going to be doing some swapping.
Here (attached) is the code i use to set up the mobo to read data from
my a/d card. It will do the same for a Sound blaster, but i'd have to
figure out how to set up the sb to do the dreq.
the only tricks to DMA as far as i can tell is that getting data from
I/O is called a read, and for almost any repetitive data acquistion (or
analog output task) you want to use single mode. Single mode just
transfers one byte/word for each dreq, which is how sb works. My code
uses autoinit, because i read int the same buffer over and over. An
audio program probably would change the DMA buffer address each time, so
autoinit wouldn't work.
then in your dma complete interrupt handler, you would want to do:
disable_dma(dma_chan);
set_dma_addr(dma_chan,differentaddress);
enable_dma(dma_chan);
I wish i could help more, but i have overcommitted myself for the next
week or so.
eric
#define REAL_TIME
#include <asm/dma.h>
#include <rtl_core.h>
#include <rtl_sync.h>
/*
dma_start_mobo sets up the dma controller on mobo
to handle dma requests from A/D board
requires address and length of data and dma channel
must run this before initiating A/D reads, or bad
things will happen. suggest running before
initialize A/D board settings
*/
int dma_start_mobo (unsigned long dma_addr,
int dma_chan,
unsigned long dma_len)
{
int status;
#ifdef REAL_TIME
rtl_irqstate_t state;
#else
unsigned long flags;
#endif
if (!dma_len || (dma_len > 0xffff))
{
printk("<1>\n dmalen no good\n"); /* Invalid length */
return -EINVAL;
}
if (((dma_addr & 0xffff)+dma_len) !=
((dma_addr + dma_len) & 0xffff))
/* We would cross a 64kb-segment */
{
printk("<1>\n dma would pass 64kbdry\n"); /* Invalid
length */
return -EINVAL;
}
if ((dma_addr + dma_len) > MAX_DMA_ADDRESS)
/* Only lower 16 MB */
{
printk("<1>\n dmabuf not in lowest 16m\n"); /* Invalid
length */
return -EINVAL;
}
#ifdef REAL_TIME
rtl_no_interrupts(state);
#else
/* Don't need any irqs here... */
save_flags (flags);
cli ();
#endif
if((status=request_dma(dma_chan,"contrlr"))!=0)
{
printk("\nno joy on request dma chan");
return status;
}
/* Get a well defined state */
disable_dma (dma_chan);
clear_dma_ff (dma_chan);
set_dma_mode (dma_chan,0x54);
/* we want to get data DMA_MODE_READ|DMA_AUTOINIT); */
set_dma_addr (dma_chan, dma_addr);
set_dma_count (dma_chan, dma_len);
enable_dma (dma_chan);
#ifdef REAL_TIME
rtl_restore_interrupts(state);
#else
restore_flags (flags);
#endif
return 0;
}
//uninstall mobo dma controller -- stop a/d brd first!
void dma_stop_mobo (int dma_chan) {
disable_dma (dma_chan);
free_dma(dma_chan);
}