Hi ! > as a person who have written ZERO PCI drivers, let me make a > guess > (apologized if wrong) Actually yes ! You are not wrong (not yet). > 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. Ok ! You confirm what i was thinking. BTW, it is the first time i go through kernel code source. :) > > > > 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. > Thank you for the tips & answers. I will check the hardware datasheet for the hardware specific details. > -- > Regards, > Peter Teoh Fernand LS -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ