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>
11 #include <asm/cacheflush.h>
12 #include <asm/pgtable.h>
14 static int ioremap_pte_range(pmd_t
*pmd
, unsigned long addr
,
15 unsigned long end
, unsigned long phys_addr
, pgprot_t prot
)
20 pfn
= phys_addr
>> PAGE_SHIFT
;
21 pte
= pte_alloc_kernel(pmd
, addr
);
25 BUG_ON(!pte_none(*pte
));
26 set_pte_at(&init_mm
, addr
, pte
, pfn_pte(pfn
, prot
));
28 } while (pte
++, addr
+= PAGE_SIZE
, addr
!= end
);
32 static inline int ioremap_pmd_range(pud_t
*pud
, unsigned long addr
,
33 unsigned long end
, unsigned long phys_addr
, pgprot_t prot
)
39 pmd
= pmd_alloc(&init_mm
, pud
, addr
);
43 next
= pmd_addr_end(addr
, end
);
44 if (ioremap_pte_range(pmd
, addr
, next
, phys_addr
+ addr
, prot
))
46 } while (pmd
++, addr
= next
, addr
!= end
);
50 static inline int ioremap_pud_range(pgd_t
*pgd
, unsigned long addr
,
51 unsigned long end
, unsigned long phys_addr
, pgprot_t prot
)
57 pud
= pud_alloc(&init_mm
, pgd
, addr
);
61 next
= pud_addr_end(addr
, end
);
62 if (ioremap_pmd_range(pud
, addr
, next
, phys_addr
+ addr
, prot
))
64 } while (pud
++, addr
= next
, addr
!= end
);
68 int ioremap_page_range(unsigned long addr
,
69 unsigned long end
, unsigned long phys_addr
, pgprot_t prot
)
80 pgd
= pgd_offset_k(addr
);
82 next
= pgd_addr_end(addr
, end
);
83 err
= ioremap_pud_range(pgd
, addr
, next
, phys_addr
+addr
, prot
);
86 } while (pgd
++, addr
= next
, addr
!= end
);
88 flush_cache_vmap(start
, end
);