Blame view

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