Subject: Re: Bus Dma Question
To: Riaz <riazr@cat.co.za>
From: Wayne Knowles <wdk@NetBSD.ORG>
List: tech-kern
Date: 08/25/2000 13:31:26
Hi Riaz,
Recently I needed to do something similar and did a bit of looking at
other device deriver implementations to help me understand bus_dma(9)
You didn't explicitly say what the problem was - I assume what the device
DMA isn't appearing in kernel memory.
On Thu, 24 Aug 2000, Riaz wrote:
> Just before we capture an image we set the first 4 bytes
> to a magic number and check those bytes when an interrupt
> is generated after a capture. If they are the same, we assume
> that the capture failed (may happen after a few minutes).
> I don't know whether the data is cached somewhere.
>
> (I know that I am transferring a ridiculous amount of data on the PCI bus)
>
> I tried "bus_dmamap_sync" but isn't that a "nop" on i386?
You should get into the habit of performing a bus_dmamap_sync even if it
it is a nop operation. The PCI bus is used on other architectures which
may require special cache ops to guarantee consistency.
> Also what is the need for creating a dmamap anyway?
You need this as the first step to getting a physical address. AFAIK it
also sets up memory management, MTRR's etc.
> Are the results I obtain to be expected or is there something I could do?
I would strongly suggest you check the return codes when calling bus_dma*
If you read the bus_dmamem_alloc(9) manual you will see you have to load
the map as well using dus_dmamap_load to get the physical memory address.
Take a look at sys/arch/mipsco/obio/if_le.c and
sys/arch/sparc/dev/if_le_obio.c for examples.
>
> ----------------------------------------------------------------------
> static void
> fg_attach_pci(parent, self, aux)
> struct device *parent, *self;
> void *aux;
> {
> struct fg_softc *sc = (void *) self;
> struct pci_attach_args *pap = aux;
> bus_space_tag_t memt;
> bus_space_handle_t memh;
> bus_size_t memsize;
> bus_dma_segment_t segs;
> int rsegs;
> caddr_t kva;
> ...
>
> pci_mapreg_map(pap, 0x10, PCI_MAPREG_TYPE_MEM, 0,&memt, &memh, NULL,
> &memsize);
> bus_dmamem_alloc(pap->pa_dmat, TOTAL_DMA, 0,
> 0,&segs,1,&rsegs,BUS_DMA_NOWAIT);
> bus_dmamem_map(pap->pa_dmat,&segs,rsegs,TOTAL_DMA,&kva,BUS_DMA_NOWAIT);
> ...
> sc->VideoPhysMem = segs.ds_addr;
> sc->VideoMapMem = kva;
> ...
> }
>
> then just before capture:
> ...
> *(int*)(sc->VideoMapMem) = 0xfacecafe;
> ...
>
> and the card transfers the image into sc->VideoPhysMem
>
> then interrupt handler (after capture):
>
> int
> fg_intr(arg)
> void *arg;
> {...
> if ( *(int*)(sc->VideoMapMem) == 0xfacecafe)
> {
> RawFail = 1;
> }
> ...
> }
Regards,
Wayne