as a person who have written ZERO PCI drivers, let me make a guess
(apologized if wrong):

On Thu, Mar 5, 2009 at 1:59 AM, Fernand LONE SANG <[email protected]> wrote:
>
> Hello everybody !
>
> I have 2 question about how DMA work, especially for PCI devices.
>
> The first one concerns the device. How can i know if a device is DMA-able ? I 
> found a function in the kernel source code called 'dma_set_mask'.  I want to 
> know which registers of the device this function sets, and how it sets it : 
> via Port I/O or MMIO, and where i can find the address where it is written ? 
> I browsed the code, but i did not managed to see from which register inside a 
> pci device are involved.

as far as i can see, it only set a field value in a structure, no
hardware involved.

int dma_set_mask(struct device *dev, u64 mask)
{
        if (!dev->dma_mask || !dma_supported(dev, mask))
                return -EIO;

        *dev->dma_mask = mask;

        return 0;
}

and from all the possible examples:

./drivers/media/video/meye.c:
        if (dma_set_mask(&meye.mchip_dev->dev, DMA_32BIT_MASK))

./drivers/net/b44.c:
        err = ssb_dma_set_mask(sdev, DMA_30BIT_MASK);

./drivers/net/wireless/b43/dma.c:
static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
                err = ssb_dma_set_mask(dev->dev, mask);
        err = b43_dma_set_mask(dev, dmamask);

./drivers/net/wireless/b43legacy/dma.c:
static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask)
                err = ssb_dma_set_mask(dev->dev, mask);
        err = b43legacy_dma_set_mask(dev, dmamask);

./drivers/net/wireless/rt2x00/rt2x00pci.c:
        if (dma_set_mask(&pci_dev->dev, DMA_32BIT_MASK)) {

./drivers/scsi/aic7xxx/aic79xx_osm_pci.c:
                    dma_set_mask(dev, DMA_64BIT_MASK) == 0)
                         dma_set_mask(dev, DMA_39BIT_MASK) == 0)
                        dma_set_mask(dev, DMA_32BIT_MASK);
                dma_set_mask(dev, DMA_32BIT_MASK);

./drivers/scsi/aic7xxx/aic7xxx_osm_pci.c:
            && dma_set_mask(dev, mask_39bit) == 0
                if (dma_set_mask(dev, DMA_32BIT_MASK)) {

./drivers/scsi/lasi700.c:
        dma_set_mask(&dev->dev, DMA_32BIT_MASK);

./drivers/scsi/qla2xxx/qla_os.c:
        if (!dma_set_mask(&ha->pdev->dev, DMA_64BIT_MASK)) {
        dma_set_mask(&ha->pdev->dev, DMA_32BIT_MASK);

./drivers/scsi/sni_53c710.c:
        dma_set_mask(&dev->dev, DMA_32BIT_MASK);

./drivers/ssb/main.c:
int ssb_dma_set_mask(struct ssb_device *dev, u64 mask)
                return dma_set_mask(dev->dev, mask);

it only have a two value involved.   so again, i don't think it is
hardware specific.

>
> The second question concern the DMA principles (precisely DMA Bus Mastering). 
> For the question, let's make the supposition that we want to make a transfert 
> from a device to RAM. How do i specify the memory address of the device from 
> where i need to copy data of a specified length to the DMA buffer? How do i 
> know where the data to be transfered begin ? In most of the documents 
> describing a driver with DMA, they never specify that point.
>

copying data to DMA buffer?   after u have done pci_iomap() u can just
memcpy() or memset() to it directly, and followed by pci_iounmap().
these and many other PCI specific API are well covered in
Documentation/PCI/pci.txt:   How to write Linux PCI drivers.

> If someone can light me on those two points, that would help me a lot in my 
> work.
>
> Fernand.
>
>

And deeper than that - PCI protocol specific, is really beyond driver
level, u can ignore that.   And after understanding the hardware
independent Linux PCI layer (pci.txt), take one simple example (eg,
drivers/video/vt8623fb.c) and delved into all the hardware specific
portion, and see how these information can be extracted from the
relevant datasheet.

For example (blanking and syncing in vt8623fb.c etc):

static int vt8623fb_blank(int blank_mode, struct fb_info *info)
{
        switch (blank_mode) {
        case FB_BLANK_UNBLANK:
                pr_debug("fb%d: unblank\n", info->node);
                svga_wcrt_mask(0x36, 0x00, 0x30);
                svga_wseq_mask(0x01, 0x00, 0x20);
                break;
        case FB_BLANK_NORMAL:
                pr_debug("fb%d: blank\n", info->node);
                svga_wcrt_mask(0x36, 0x00, 0x30);
                svga_wseq_mask(0x01, 0x20, 0x20);
                break;
        case FB_BLANK_HSYNC_SUSPEND:
                pr_debug("fb%d: DPMS standby (hsync off)\n", info->node);
                svga_wcrt_mask(0x36, 0x10, 0x30);
                svga_wseq_mask(0x01, 0x20, 0x20);
                break;
        case FB_BLANK_VSYNC_SUSPEND:
                pr_debug("fb%d: DPMS suspend (vsync off)\n", info->node);
                svga_wcrt_mask(0x36, 0x20, 0x30);
                svga_wseq_mask(0x01, 0x20, 0x20);
                break;

These are setting the DMA memory to implement some hardware feature for eg.

>
>
>
> --
> To unsubscribe from this list: send an email with
> "unsubscribe kernelnewbies" to [email protected]
> Please read the FAQ at http://kernelnewbies.org/FAQ
>
>



-- 
Regards,
Peter Teoh

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to [email protected]
Please read the FAQ at http://kernelnewbies.org/FAQ

Reply via email to