Initial. Don't... just don't ask.
This commit is contained in:
commit
00bae13bba
586 changed files with 129057 additions and 0 deletions
358
kernel/svgalib_helper/virtual.c
Normal file
358
kernel/svgalib_helper/virtual.c
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
#ifdef SVGA_HELPER_VIRTUAL
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h> /* cli(), *_flags */
|
||||
#include <asm/segment.h> /* memcpy and such */
|
||||
#include <asm/io.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/wrapper.h>
|
||||
#include "svgalib_helper.h"
|
||||
|
||||
/*******************************/
|
||||
/* Memory management functions */
|
||||
/* from kernel:/drivers/media/video/bttv-driver.c */
|
||||
/*******************************/
|
||||
|
||||
#define MDEBUG(x) do { } while(0) /* Debug memory management */
|
||||
|
||||
/* [DaveM] I've recoded most of this so that:
|
||||
* 1) It's easier to tell what is happening
|
||||
* 2) It's more portable, especially for translating things
|
||||
* out of vmalloc mapped areas in the kernel.
|
||||
* 3) Less unnecessary translations happen.
|
||||
*
|
||||
* The code used to assume that the kernel vmalloc mappings
|
||||
* existed in the page tables of every process, this is simply
|
||||
* not guarenteed. We now use pgd_offset_k which is the
|
||||
* defined way to get at the kernel page tables.
|
||||
*/
|
||||
|
||||
/* Given PGD from the address space's page table, return the kernel
|
||||
* virtual mapping of the physical memory mapped at ADR.
|
||||
*/
|
||||
static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
|
||||
{
|
||||
unsigned long ret = 0UL;
|
||||
pmd_t *pmd;
|
||||
pte_t *ptep, pte;
|
||||
|
||||
if (!pgd_none(*pgd)) {
|
||||
pmd = pmd_offset(pgd, adr);
|
||||
if (!pmd_none(*pmd)) {
|
||||
ptep = pte_offset(pmd, adr);
|
||||
pte = *ptep;
|
||||
if(pte_present(pte)) {
|
||||
ret = (unsigned long) page_address(pte_page(pte));
|
||||
ret |= (adr & (PAGE_SIZE - 1));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long uvirt_to_bus(unsigned long adr)
|
||||
{
|
||||
unsigned long kva, ret;
|
||||
|
||||
kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
|
||||
ret = virt_to_bus((void *)kva);
|
||||
MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long uvirt_to_pa(unsigned long adr)
|
||||
{
|
||||
unsigned long kva, ret;
|
||||
|
||||
kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
|
||||
ret = virt_to_phys((void *)kva);
|
||||
MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long kvirt_to_bus(unsigned long adr)
|
||||
{
|
||||
unsigned long va, kva, ret;
|
||||
|
||||
va = VMALLOC_VMADDR(adr);
|
||||
kva = uvirt_to_kva(pgd_offset_k(va), va);
|
||||
ret = virt_to_bus((void *)kva);
|
||||
MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Here we want the physical address of the memory.
|
||||
* This is used when initializing the contents of the
|
||||
* area and marking the pages as reserved.
|
||||
*/
|
||||
static inline unsigned long kvirt_to_pa(unsigned long adr)
|
||||
{
|
||||
unsigned long va, kva, ret;
|
||||
|
||||
va = VMALLOC_VMADDR(adr);
|
||||
kva = uvirt_to_kva(pgd_offset_k(va), va);
|
||||
ret = __pa(kva);
|
||||
MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void * rvmalloc(signed long size)
|
||||
{
|
||||
void * mem;
|
||||
unsigned long adr, page;
|
||||
|
||||
mem=vmalloc_32(size);
|
||||
if (mem)
|
||||
{
|
||||
memset(mem, 0, size); /* Clear the ram out, no junk to the user */
|
||||
adr=(unsigned long) mem;
|
||||
while (size > 0)
|
||||
{
|
||||
page = kvirt_to_pa(adr);
|
||||
mem_map_reserve(virt_to_page(__va(page)));
|
||||
adr+=PAGE_SIZE;
|
||||
size-=PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static int pag_lock(unsigned long addr)
|
||||
{
|
||||
unsigned long page;
|
||||
unsigned long kva;
|
||||
|
||||
kva = uvirt_to_kva(pgd_offset(current->mm, addr), addr);
|
||||
if(kva)
|
||||
{
|
||||
lock_it:
|
||||
page = uvirt_to_pa((unsigned long)addr);
|
||||
LockPage(virt_to_page(__va(page)));
|
||||
SetPageReserved(virt_to_page(__va(page)));
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_from_user(&page,(char *)addr,1); /* try access it */
|
||||
kva = uvirt_to_kva(pgd_offset(current->mm, addr), addr);
|
||||
if(kva) goto lock_it;
|
||||
else return EPERM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pag_unlock(unsigned long addr)
|
||||
{
|
||||
unsigned long page;
|
||||
unsigned long kva;
|
||||
|
||||
kva = uvirt_to_kva(pgd_offset(current->mm, addr), addr);
|
||||
if(kva)
|
||||
{
|
||||
page = uvirt_to_pa((unsigned long)addr);
|
||||
UnlockPage(virt_to_page(__va(page)));
|
||||
ClearPageReserved(virt_to_page(__va(page)));
|
||||
return 0;
|
||||
}
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
|
||||
static void rvfree(void * mem, signed long size)
|
||||
{
|
||||
unsigned long adr, page;
|
||||
|
||||
if (mem)
|
||||
{
|
||||
adr=(unsigned long) mem;
|
||||
while (size > 0)
|
||||
{
|
||||
page = kvirt_to_pa(adr);
|
||||
mem_map_unreserve(virt_to_page(__va(page)));
|
||||
adr+=PAGE_SIZE;
|
||||
size-=PAGE_SIZE;
|
||||
}
|
||||
vfree(mem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int dhahelper_virt_to_phys(dhahelper_vmi_t *arg)
|
||||
{
|
||||
dhahelper_vmi_t mem;
|
||||
unsigned long i,nitems;
|
||||
char *addr;
|
||||
if (copy_from_user(&mem, arg, sizeof(dhahelper_vmi_t)))
|
||||
{
|
||||
if (debug > 0)
|
||||
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
nitems = mem.length / PAGE_SIZE;
|
||||
if(mem.length % PAGE_SIZE) nitems++;
|
||||
addr = mem.virtaddr;
|
||||
for(i=0;i<nitems;i++)
|
||||
{
|
||||
unsigned long result;
|
||||
result = uvirt_to_pa((unsigned long)addr);
|
||||
if (copy_to_user(&mem.realaddr[i], &result, sizeof(unsigned long)))
|
||||
{
|
||||
if (debug > 0)
|
||||
printk(KERN_ERR "dhahelper: failed copy to userspace\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhahelper_virt_to_bus(dhahelper_vmi_t *arg)
|
||||
{
|
||||
dhahelper_vmi_t mem;
|
||||
unsigned long i,nitems;
|
||||
char *addr;
|
||||
if (copy_from_user(&mem, arg, sizeof(dhahelper_vmi_t)))
|
||||
{
|
||||
if (debug > 0)
|
||||
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
nitems = mem.length / PAGE_SIZE;
|
||||
if(mem.length % PAGE_SIZE) nitems++;
|
||||
addr = mem.virtaddr;
|
||||
for(i=0;i<nitems;i++)
|
||||
{
|
||||
unsigned long result;
|
||||
result = uvirt_to_bus((unsigned long)addr);
|
||||
if (copy_to_user(&mem.realaddr[i], &result, sizeof(unsigned long)))
|
||||
{
|
||||
if (debug > 0)
|
||||
printk(KERN_ERR "dhahelper: failed copy to userspace\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int dhahelper_alloc_pa(dhahelper_mem_t *arg)
|
||||
{
|
||||
dhahelper_mem_t mem;
|
||||
if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))
|
||||
{
|
||||
if (debug > 0)
|
||||
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
mem.addr = rvmalloc(mem.length);
|
||||
if (copy_to_user(arg, &mem, sizeof(dhahelper_mem_t)))
|
||||
{
|
||||
if (debug > 0)
|
||||
printk(KERN_ERR "dhahelper: failed copy to userspace\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhahelper_free_pa(dhahelper_mem_t *arg)
|
||||
{
|
||||
dhahelper_mem_t mem;
|
||||
if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))
|
||||
{
|
||||
if (debug > 0)
|
||||
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
rvfree(mem.addr,mem.length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhahelper_lock_mem(dhahelper_mem_t *arg)
|
||||
{
|
||||
dhahelper_mem_t mem;
|
||||
int retval;
|
||||
unsigned long i,nitems,addr;
|
||||
if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))
|
||||
{
|
||||
if (debug > 0)
|
||||
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
nitems = mem.length / PAGE_SIZE;
|
||||
if(mem.length % PAGE_SIZE) nitems++;
|
||||
addr = (unsigned long)mem.addr;
|
||||
for(i=0;i<nitems;i++)
|
||||
{
|
||||
retval = pag_lock((unsigned long)addr);
|
||||
if(retval)
|
||||
{
|
||||
unsigned long j;
|
||||
addr = (unsigned long)mem.addr;
|
||||
for(j=0;j<i;j++)
|
||||
{
|
||||
pag_unlock(addr);
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhahelper_unlock_mem(dhahelper_mem_t *arg)
|
||||
{
|
||||
dhahelper_mem_t mem;
|
||||
int retval;
|
||||
unsigned long i,nitems,addr;
|
||||
if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t)))
|
||||
{
|
||||
if (debug > 0)
|
||||
printk(KERN_ERR "dhahelper: failed copy from userspace\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
nitems = mem.length / PAGE_SIZE;
|
||||
if(mem.length % PAGE_SIZE) nitems++;
|
||||
addr = (unsigned long)mem.addr;
|
||||
for(i=0;i<nitems;i++)
|
||||
{
|
||||
retval = pag_unlock((unsigned long)addr);
|
||||
if(retval) return retval;
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhahelper_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
if (debug > 1)
|
||||
printk(KERN_DEBUG "dhahelper: ioctl(cmd=%x, arg=%lx)\n",
|
||||
cmd, arg);
|
||||
|
||||
if (MINOR(inode->i_rdev) != 0)
|
||||
return -ENXIO;
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case DHAHELPER_GET_VERSION: return dhahelper_get_version((int *)arg);
|
||||
case DHAHELPER_PORT: return dhahelper_port((dhahelper_port_t *)arg);
|
||||
case DHAHELPER_VIRT_TO_PHYS:return dhahelper_virt_to_phys((dhahelper_vmi_t *)arg);
|
||||
case DHAHELPER_VIRT_TO_BUS: return dhahelper_virt_to_bus((dhahelper_vmi_t *)arg);
|
||||
case DHAHELPER_ALLOC_PA:return dhahelper_alloc_pa((dhahelper_mem_t *)arg);
|
||||
case DHAHELPER_FREE_PA: return dhahelper_free_pa((dhahelper_mem_t *)arg);
|
||||
case DHAHELPER_LOCK_MEM: return dhahelper_lock_mem((dhahelper_mem_t *)arg);
|
||||
case DHAHELPER_UNLOCK_MEM: return dhahelper_unlock_mem((dhahelper_mem_t *)arg);
|
||||
default:
|
||||
if (debug > 0)
|
||||
printk(KERN_ERR "dhahelper: invalid ioctl (%x)\n", cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue