/*
 *  mem_op.h 1.3 1996/11/11 03:58:48 (David Hinds)
 */

#ifndef _LINUX_MEM_OP_H
#define _LINUX_MEM_OP_H

/*
   If UNSAFE_MEMCPY is defined, we use the (optimized) system routines
   to copy between a card and kernel memory.  These routines do 32-bit
   operations which may not work with all PCMCIA controllers.  The
   safe versions defined here will do only 8-bit and 16-bit accesses.
*/

#ifdef UNSAFE_MEMCPY

#define copy_from_pc memcpy_fromio
#define copy_to_pc memcpy_toio

extern inline void copy_pc_to_user(void *to, const void *from, size_t n)
{
    size_t odd = (n & 3);
    n -= odd;
    while (n) {
	put_user(readl(from), (long *)to);
	from += 4; to += 4; n -= 4;
    }
    while (odd--)
	put_user(readb(from++), (char *)to++);
}

extern inline void copy_user_to_pc(void *to, const void *from, size_t n)
{
    long l;
    char c;
    size_t odd = (n & 3);
    n -= odd;
    while (n) {
	get_user(l, (long *)from);
	writel(l, to);
	to += 4; from += 4; n -= 4;
    }
    while (odd--) {
	get_user(c, (char *)from++);
	writeb(c, to++);
    }
}

#else /* UNSAFE_MEMCPY */

extern inline void copy_from_pc(void *to, const void *from, size_t n)
{
    size_t odd = (n & 1);
    n -= odd;
    while (n) {
	*(u_short *)to = readw(from);
	to += 2; from += 2; n -= 2;
    }
    if (odd)
	*(u_char *)to = readb(from);
}

extern inline void copy_to_pc(void *to, const void *from, size_t n)
{
    size_t odd = (n & 1);
    n -= odd;
    while (n) {
	writew(*(u_short *)from, to);
	to += 2; from += 2; n -= 2;
    }
    if (odd)
	writeb(*(u_char *)from, to);
}

extern inline void copy_pc_to_user(void *to, const void *from, size_t n)
{
    size_t odd = (n & 1);
    n -= odd;
    while (n) {
	put_user(readw(from), (short *)to);
	to += 2; from += 2; n -= 2;
    }
    if (odd)
	put_user(readb(from), (char *)to);
}

extern inline void copy_user_to_pc(void *to, const void *from, size_t n)
{
    short s;
    char c;
    size_t odd = (n & 1);
    n -= odd;
    while (n) {
	get_user(s, (short *)from);
	writew(s, to);
	to += 2; from += 2; n -= 2;
    }
    if (odd) {
	get_user(c, (char *)from);
	writeb(c, to);
    }
}

#endif /* UNSAFE_MEMCPY */

#endif /* _LINUX_MEM_OP_H */
