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 <asm/cacheflush.h>
13 #include <asm/pgtable.h>
15 static int ioremap_pte_range(pmd_t
*pmd
, unsigned long addr
,
16 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
21 pfn
= phys_addr
>> PAGE_SHIFT
;
22 pte
= pte_alloc_kernel(pmd
, addr
);
26 BUG_ON(!pte_none(*pte
));
27 set_pte_at(&init_mm
, addr
, pte
, pfn_pte(pfn
, prot
));
29 } while (pte
++, addr
+= PAGE_SIZE
, addr
!= end
);
33 static inline int ioremap_pmd_range(pud_t
*pud
, unsigned long addr
,
34 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
40 pmd
= pmd_alloc(&init_mm
, pud
, addr
);
44 next
= pmd_addr_end(addr
, end
);
45 if (ioremap_pte_range(pmd
, addr
, next
, phys_addr
+ addr
, prot
))
47 } while (pmd
++, addr
= next
, addr
!= end
);
51 static inline int ioremap_pud_range(pgd_t
*pgd
, unsigned long addr
,
52 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
58 pud
= pud_alloc(&init_mm
, pgd
, addr
);
62 next
= pud_addr_end(addr
, end
);
63 if (ioremap_pmd_range(pud
, addr
, next
, phys_addr
+ addr
, prot
))
65 } while (pud
++, addr
= next
, addr
!= end
);
69 int ioremap_page_range(unsigned long addr
,
70 unsigned long end
, phys_addr_t phys_addr
, pgprot_t prot
)
81 pgd
= pgd_offset_k(addr
);
83 next
= pgd_addr_end(addr
, end
);
84 err
= ioremap_pud_range(pgd
, addr
, next
, phys_addr
+addr
, prot
);
87 } while (pgd
++, addr
= next
, addr
!= end
);
89 flush_cache_vmap(start
, end
);