/* Copyright (C) 2008 Emmanuel Varoquaux This file is part of XOS. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Cette implementation est gourmande en memoire, surtout pour les petits * fichiers. La memoire allouee pour la structure ne fait que croitre, jusqu'a * la destruction du fichier. */ #include #include #include #include #include #define TABLE_INDEX(offset) ((offset) / PAGE_SIZE) #define DIR_INDEX(offset) ((offset) / PAGE_SIZE / (PAGE_SIZE / 4)) void mapping_init(struct mapping_struct *mapping) { mapping->directory = NULL; } void mapping_destroy(struct mapping_struct *mapping) { unsigned long **dir_ent; if (mapping->directory) { for (dir_ent = &mapping->directory[0]; dir_ent < &mapping->directory[PAGE_SIZE / 4]; dir_ent++) if (*dir_ent) kfree(*dir_ent, PAGE_SIZE); kfree(mapping->directory, PAGE_SIZE); } } /* Transfert src dans dest. */ void mapping_copy(const struct mapping_struct *src, struct mapping_struct *dest) { dest->directory = src->directory; } unsigned long mapping_get_page_frame(const struct mapping_struct *mapping, unsigned long offset) { unsigned long *table; if (!mapping->directory) return 0; if (!(table = mapping->directory[DIR_INDEX(offset)])) return 0; return table[TABLE_INDEX(offset)]; } /* L'entree correspondant a offset doit etre vide (sinon elle est ecrasee). * Cette fonction ne garantie pas que l'operation a reussie, en particulier * s'il n'y a plus de memoire. */ void mapping_set_page_frame(struct mapping_struct *mapping, unsigned long offset, unsigned long page_frame) { unsigned long *table; if (!mapping->directory) { if (!(mapping->directory = kmalloc(PAGE_SIZE))) return; memset(mapping->directory, 0, PAGE_SIZE); } if (!(table = mapping->directory[DIR_INDEX(offset)])) { if (!(table = kmalloc(PAGE_SIZE))) return; memset(table, 0, PAGE_SIZE); mapping->directory[DIR_INDEX(offset)] = table; } table[TABLE_INDEX(offset)] = page_frame; } /* Si le cadre de page n'est pas dans la projection, aucune operation n'est * effectuee. */ void mapping_delete_page_frame(struct mapping_struct *mapping, unsigned long offset, unsigned long page_frame) { unsigned long *table; if (!mapping->directory) return; if (!(table = mapping->directory[DIR_INDEX(offset)])) return; if (table[TABLE_INDEX(offset)] == page_frame) table[TABLE_INDEX(offset)] = 0; }