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 <flone_sa@xxxxxxxxx> 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 ecartis@xxxxxxxxxxxx > Please read the FAQ at http://kernelnewbies.org/FAQ > > -- Regards, Peter Teoh -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ