OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [sparc/] [mm/] [generic.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1624 jcastillo
/* $Id: generic.c,v 1.1 2005-12-20 09:50:49 jcastillo Exp $
2
 * generic.c: Generic Sparc mm routines that are not dependent upon
3
 *            MMU type but are Sparc specific.
4
 *
5
 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
6
 */
7
 
8
#include <linux/kernel.h>
9
#include <linux/mm.h>
10
#include <linux/swap.h>
11
 
12
#include <asm/pgtable.h>
13
#include <asm/page.h>
14
 
15
static inline void forget_pte(pte_t page)
16
{
17
        if (pte_none(page))
18
                return;
19
        if (pte_present(page)) {
20
                unsigned long addr = pte_page(page);
21
                if (addr >= high_memory || PageReserved(mem_map+MAP_NR(addr)))
22
                        return;
23
                free_page(addr);
24
                if (current->mm->rss <= 0)
25
                        return;
26
                current->mm->rss--;
27
                return;
28
        }
29
        swap_free(pte_val(page));
30
}
31
 
32
/* Remap IO memory, the same way as remap_page_range(), but use
33
 * the obio memory space.
34
 *
35
 * They use a pgprot that sets PAGE_IO and does not check the
36
 * mem_map table as this is independent of normal memory.
37
 */
38
static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
39
        unsigned long offset, pgprot_t prot, int space)
40
{
41
        unsigned long end;
42
 
43
        address &= ~PMD_MASK;
44
        end = address + size;
45
        if (end > PMD_SIZE)
46
                end = PMD_SIZE;
47
        do {
48
                pte_t oldpage = *pte;
49
                pte_clear(pte);
50
                set_pte(pte, mk_pte_io(offset, prot, space));
51
                forget_pte(oldpage);
52
                address += PAGE_SIZE;
53
                offset += PAGE_SIZE;
54
                pte++;
55
        } while (address < end);
56
}
57
 
58
static inline int io_remap_pmd_range(pmd_t * pmd, unsigned long address, unsigned long size,
59
        unsigned long offset, pgprot_t prot, int space)
60
{
61
        unsigned long end;
62
 
63
        address &= ~PGDIR_MASK;
64
        end = address + size;
65
        if (end > PGDIR_SIZE)
66
                end = PGDIR_SIZE;
67
        offset -= address;
68
        do {
69
                pte_t * pte = pte_alloc(pmd, address);
70
                if (!pte)
71
                        return -ENOMEM;
72
                io_remap_pte_range(pte, address, end - address, address + offset, prot, space);
73
                address = (address + PMD_SIZE) & PMD_MASK;
74
                pmd++;
75
        } while (address < end);
76
        return 0;
77
}
78
 
79
int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space)
80
{
81
        int error = 0;
82
        pgd_t * dir;
83
        unsigned long beg = from;
84
        unsigned long end = from + size;
85
 
86
        pgprot_val(prot) = pg_iobits;
87
        offset -= from;
88
        dir = pgd_offset(current->mm, from);
89
        flush_cache_range(current->mm, beg, end);
90
        while (from < end) {
91
                pmd_t *pmd = pmd_alloc(dir, from);
92
                error = -ENOMEM;
93
                if (!pmd)
94
                        break;
95
                error = io_remap_pmd_range(pmd, from, end - from, offset + from, prot, space);
96
                if (error)
97
                        break;
98
                from = (from + PGDIR_SIZE) & PGDIR_MASK;
99
                dir++;
100
        }
101
        flush_tlb_range(current->mm, beg, end);
102
        return error;
103
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.