linux/arch/i386/kernel/pci-dma.c
<<
>>
Prefs
   1/*
   2 * Dynamic DMA mapping support.
   3 *
   4 * On i386 there is no hardware dynamic DMA address translation,
   5 * so consistent alloc/free are merely page allocation/freeing.
   6 * The rest of the dynamic DMA mapping interface is implemented
   7 * in asm/pci.h.
   8 */
   9
  10#include <linux/types.h>
  11#include <linux/mm.h>
  12#include <linux/string.h>
  13#include <linux/pci.h>
  14#include <linux/module.h>
  15#include <linux/pci.h>
  16#include <asm/io.h>
  17
  18struct dma_coherent_mem {
  19        void            *virt_base;
  20        u32             device_base;
  21        int             size;
  22        int             flags;
  23        unsigned long   *bitmap;
  24};
  25
  26void *dma_alloc_coherent(struct device *dev, size_t size,
  27                           dma_addr_t *dma_handle, gfp_t gfp)
  28{
  29        void *ret;
  30        struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
  31        int order = get_order(size);
  32        /* ignore region specifiers */
  33        gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
  34
  35        if (mem) {
  36                int page = bitmap_find_free_region(mem->bitmap, mem->size,
  37                                                     order);
  38                if (page >= 0) {
  39                        *dma_handle = mem->device_base + (page << PAGE_SHIFT);
  40                        ret = mem->virt_base + (page << PAGE_SHIFT);
  41                        memset(ret, 0, size);
  42                        return ret;
  43                }
  44                if (mem->flags & DMA_MEMORY_EXCLUSIVE)
  45                        return NULL;
  46        }
  47
  48        if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
  49                gfp |= GFP_DMA;
  50
  51        ret = (void *)__get_free_pages(gfp, order);
  52
  53        if (ret != NULL) {
  54                memset(ret, 0, size);
  55                *dma_handle = virt_to_phys(ret);
  56        }
  57        return ret;
  58}
  59EXPORT_SYMBOL(dma_alloc_coherent);
  60
  61void dma_free_coherent(struct device *dev, size_t size,
  62                         void *vaddr, dma_addr_t dma_handle)
  63{
  64        struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
  65        int order = get_order(size);
  66        
  67        if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
  68                int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
  69
  70                bitmap_release_region(mem->bitmap, page, order);
  71        } else
  72                free_pages((unsigned long)vaddr, order);
  73}
  74EXPORT_SYMBOL(dma_free_coherent);
  75
  76int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
  77                                dma_addr_t device_addr, size_t size, int flags)
  78{
  79        void __iomem *mem_base = NULL;
  80        int pages = size >> PAGE_SHIFT;
  81        int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
  82
  83        if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
  84                goto out;
  85        if (!size)
  86                goto out;
  87        if (dev->dma_mem)
  88                goto out;
  89
  90        /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
  91
  92        mem_base = ioremap(bus_addr, size);
  93        if (!mem_base)
  94                goto out;
  95
  96        dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
  97        if (!dev->dma_mem)
  98                goto out;
  99        dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
 100        if (!dev->dma_mem->bitmap)
 101                goto free1_out;
 102
 103        dev->dma_mem->virt_base = mem_base;
 104        dev->dma_mem->device_base = device_addr;
 105        dev->dma_mem->size = pages;
 106        dev->dma_mem->flags = flags;
 107
 108        if (flags & DMA_MEMORY_MAP)
 109                return DMA_MEMORY_MAP;
 110
 111        return DMA_MEMORY_IO;
 112
 113 free1_out:
 114        kfree(dev->dma_mem);
 115 out:
 116        if (mem_base)
 117                iounmap(mem_base);
 118        return 0;
 119}
 120EXPORT_SYMBOL(dma_declare_coherent_memory);
 121
 122void dma_release_declared_memory(struct device *dev)
 123{
 124        struct dma_coherent_mem *mem = dev->dma_mem;
 125        
 126        if(!mem)
 127                return;
 128        dev->dma_mem = NULL;
 129        iounmap(mem->virt_base);
 130        kfree(mem->bitmap);
 131        kfree(mem);
 132}
 133EXPORT_SYMBOL(dma_release_declared_memory);
 134
 135void *dma_mark_declared_memory_occupied(struct device *dev,
 136                                        dma_addr_t device_addr, size_t size)
 137{
 138        struct dma_coherent_mem *mem = dev->dma_mem;
 139        int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
 140        int pos, err;
 141
 142        if (!mem)
 143                return ERR_PTR(-EINVAL);
 144
 145        pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
 146        err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
 147        if (err != 0)
 148                return ERR_PTR(err);
 149        return mem->virt_base + (pos << PAGE_SHIFT);
 150}
 151EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
 152
 153#ifdef CONFIG_PCI
 154/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
 155
 156int forbid_dac;
 157EXPORT_SYMBOL(forbid_dac);
 158
 159static __devinit void via_no_dac(struct pci_dev *dev)
 160{
 161        if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
 162                printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
 163                forbid_dac = 1;
 164        }
 165}
 166DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
 167
 168static int check_iommu(char *s)
 169{
 170        if (!strcmp(s, "usedac")) {
 171                forbid_dac = -1;
 172                return 1;
 173        }
 174        return 0;
 175}
 176__setup("iommu=", check_iommu);
 177#endif
 178
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.