The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/lib/ioremap.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Re-map IO memory to kernel address space so that we can access it.
    3  * This is needed for high PCI addresses that aren't mapped in the
    4  * 640k-1MB IO memory area on PC's
    5  *
    6  * (C) Copyright 1995 1996 Linus Torvalds
    7  */
    8 #include <linux/vmalloc.h>
    9 #include <linux/mm.h>
   10 #include <linux/sched.h>
   11 #include <linux/io.h>
   12 #include <linux/export.h>
   13 #include <asm/cacheflush.h>
   14 #include <asm/pgtable.h>
   15 
   16 static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
   17                 unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
   18 {
   19         pte_t *pte;
   20         u64 pfn;
   21 
   22         pfn = phys_addr >> PAGE_SHIFT;
   23         pte = pte_alloc_kernel(pmd, addr);
   24         if (!pte)
   25                 return -ENOMEM;
   26         do {
   27                 BUG_ON(!pte_none(*pte));
   28                 set_pte_at(&init_mm, addr, pte, pfn_pte(pfn, prot));
   29                 pfn++;
   30         } while (pte++, addr += PAGE_SIZE, addr != end);
   31         return 0;
   32 }
   33 
   34 static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
   35                 unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
   36 {
   37         pmd_t *pmd;
   38         unsigned long next;
   39 
   40         phys_addr -= addr;
   41         pmd = pmd_alloc(&init_mm, pud, addr);
   42         if (!pmd)
   43                 return -ENOMEM;
   44         do {
   45                 next = pmd_addr_end(addr, end);
   46                 if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, prot))
   47                         return -ENOMEM;
   48         } while (pmd++, addr = next, addr != end);
   49         return 0;
   50 }
   51 
   52 static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
   53                 unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
   54 {
   55         pud_t *pud;
   56         unsigned long next;
   57 
   58         phys_addr -= addr;
   59         pud = pud_alloc(&init_mm, pgd, addr);
   60         if (!pud)
   61                 return -ENOMEM;
   62         do {
   63                 next = pud_addr_end(addr, end);
   64                 if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, prot))
   65                         return -ENOMEM;
   66         } while (pud++, addr = next, addr != end);
   67         return 0;
   68 }
   69 
   70 int ioremap_page_range(unsigned long addr,
   71                        unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
   72 {
   73         pgd_t *pgd;
   74         unsigned long start;
   75         unsigned long next;
   76         int err;
   77 
   78         BUG_ON(addr >= end);
   79 
   80         start = addr;
   81         phys_addr -= addr;
   82         pgd = pgd_offset_k(addr);
   83         do {
   84                 next = pgd_addr_end(addr, end);
   85                 err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, prot);
   86                 if (err)
   87                         break;
   88         } while (pgd++, addr = next, addr != end);
   89 
   90         flush_cache_vmap(start, end);
   91 
   92         return err;
   93 }
   94 EXPORT_SYMBOL_GPL(ioremap_page_range);

Cache object: ce3e72fd6f5501c9ac2132311e9cf7bb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.