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
6 * (C) Copyright 1995 1996 Linus Torvalds
8 #include <linux/vmalloc.h>
10 #include <linux/sched.h>
12 #include <linux/module.h>
13 #include <asm/cacheflush.h>
14 #include <asm/pgtable.h>
16 static int ioremap_pte_range(pmd_t
*pmd
, unsigned long addr
,
17 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
22 pfn
= phys_addr
>> PAGE_SHIFT
;
23 pte
= pte_alloc_kernel(pmd
, addr
);
27 BUG_ON(!pte_none(*pte
));
28 set_pte_at(&init_mm
, addr
, pte
, pfn_pte(pfn
, prot
));
30 } while (pte
++, addr
+= PAGE_SIZE
, addr
!= end
);
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
)
41 pmd
= pmd_alloc(&init_mm
, pud
, addr
);
45 next
= pmd_addr_end(addr
, end
);
46 if (ioremap_pte_range(pmd
, addr
, next
, phys_addr
+ addr
, prot
))
48 } while (pmd
++, addr
= next
, addr
!= end
);
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
)
59 pud
= pud_alloc(&init_mm
, pgd
, addr
);
63 next
= pud_addr_end(addr
, end
);
64 if (ioremap_pmd_range(pud
, addr
, next
, phys_addr
+ addr
, prot
))
66 } while (pud
++, addr
= next
, addr
!= end
);
70 int ioremap_page_range(unsigned long addr
,
71 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
82 pgd
= pgd_offset_k(addr
);
84 next
= pgd_addr_end(addr
, end
);
85 err
= ioremap_pud_range(pgd
, addr
, next
, phys_addr
+addr
, prot
);
88 } while (pgd
++, addr
= next
, addr
!= end
);
90 flush_cache_vmap(start
, end
);
94 EXPORT_SYMBOL_GPL(ioremap_page_range
);