/*
 *	User access routines for the kernel.
 */
 
#include <linuxmt/types.h>
#include <linuxmt/sched.h>
#include <arch/segment.h>
#include <linuxmt/mm.h>
#include <linuxmt/errno.h>

int verify_area(mode,ptr,len)
int mode;
char *ptr;
unsigned int len;
{
	/*
	 *	Kernel tasks can always access
	 */
	if(get_ds()==current->t_regs.ds)
		return 0;
	/*
	 *	User process boundaries
	 */
	
	if((unsigned int)(ptr+len) > current->t_endstack)
		return -EFAULT;
		
	return 0;
}

/*
 *	FIXME: These are __Incredibly__ inefficient.
 */
 
void memcpy_fromfs(daddr,saddr,len)
char *daddr;
char *saddr;
int len;
{
	while(len>0)
	{
		*daddr++=peekb(current->t_regs.ds,saddr++);
		len--;
	}
}

void memcpy_tofs(daddr,saddr,len)
char *daddr;
char *saddr;
int len;
{
	while(len>0)
	{
		pokeb(current->t_regs.ds,daddr++,*saddr++);
		len--;
	}
}

unsigned long get_fs_long(dv)
unsigned long *dv;
{
	unsigned long retv;
	memcpy_fromfs(&retv,dv,4);
	return retv;
}

void put_fs_long(dv,dp)
unsigned long dv;
unsigned long *dp;
{
	memcpy_tofs(dp,&dv,4);
}

unsigned char get_fs_byte(dv)
unsigned char *dv;
{
	unsigned char retv;
	memcpy_fromfs(&retv,dv,1);
	return retv;
}

void put_fs_byte(dv,dp)
unsigned char dv;
unsigned char *dp;
{
	memcpy_tofs(dp,&dv,1);
}

unsigned int get_fs_word(dv)
unsigned int *dv;
{
	unsigned char retv;
	memcpy_fromfs(&retv,dv,2);
	return retv;
}

void put_fs_word(dv,dp)
unsigned int dv;
unsigned int *dp;
{
	memcpy_tofs(dp,&dv,2);
}

int fs_memcmp(p1,p2,len)
unsigned char *p1;
unsigned char *p2;
int len;
{
	while(len)
	{
		unsigned char c=peekb(current->t_regs.ds,p1++);
		if(c<*p2)
			return -1;
		if(c>*p2)
			return 1;
		p2++;
		len--;
	}
	return 0;
}
