PeeCeeI.c 3.8 KB
Newer Older
A
Adrian Bunk 已提交
1
/*
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9
 * PeeCeeI.c: The emerging standard...
 *
 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
 */

#include <asm/io.h>
#include <asm/byteorder.h>

10
void outsb(unsigned long __addr, const void *src, unsigned long count)
L
Linus Torvalds 已提交
11
{
12
	void __iomem *addr = (void __iomem *) __addr;
L
Linus Torvalds 已提交
13 14
	const u8 *p = src;

15
	while (count--)
L
Linus Torvalds 已提交
16 17 18
		outb(*p++, addr);
}

19
void outsw(unsigned long __addr, const void *src, unsigned long count)
L
Linus Torvalds 已提交
20
{
21 22
	void __iomem *addr = (void __iomem *) __addr;

23 24 25
	while (count--) {
		__raw_writew(*(u16 *)src, addr);
		src += sizeof(u16);
L
Linus Torvalds 已提交
26 27 28
	}
}

29
void outsl(unsigned long __addr, const void *src, unsigned long count)
L
Linus Torvalds 已提交
30
{
31
	void __iomem *addr = (void __iomem *) __addr;
32
	u32 l, l2;
33

34 35
	if (!count)
		return;
L
Linus Torvalds 已提交
36

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
	switch (((unsigned long)src) & 0x3) {
	case 0x0:
		/* src is naturally aligned */
		while (count--) {
			__raw_writel(*(u32 *)src, addr);
			src += sizeof(u32);
		}
		break;
	case 0x2:
		/* 2-byte alignment */
		while (count--) {
			l = (*(u16 *)src) << 16;
			l |= *(u16 *)(src + sizeof(u16));
			__raw_writel(l, addr);
			src += sizeof(u32);
		}
		break;
	case 0x1:
		/* Hold three bytes in l each time, grab a byte from l2 */
		l = (*(u8 *)src) << 24;
		l |= (*(u16 *)(src + sizeof(u8))) << 8;
		src += sizeof(u8) + sizeof(u16);
		while (count--) {
			l2 = *(u32 *)src;
			l |= (l2 >> 24);
			__raw_writel(l, addr);
			l = l2 << 8;
			src += sizeof(u32);
		}
		break;
	case 0x3:
		/* Hold a byte in l each time, grab 3 bytes from l2 */
		l = (*(u8 *)src) << 24;
		src += sizeof(u8);
		while (count--) {
			l2 = *(u32 *)src;
			l |= (l2 >> 8);
			__raw_writel(l, addr);
			l = l2 << 24;
			src += sizeof(u32);
L
Linus Torvalds 已提交
77
		}
78
		break;
L
Linus Torvalds 已提交
79 80 81
	}
}

82
void insb(unsigned long __addr, void *dst, unsigned long count)
L
Linus Torvalds 已提交
83
{
84 85 86
	void __iomem *addr = (void __iomem *) __addr;

	if (count) {
L
Linus Torvalds 已提交
87 88 89
		u32 *pi;
		u8 *pb = dst;

90
		while ((((unsigned long)pb) & 0x3) && count--)
L
Linus Torvalds 已提交
91 92
			*pb++ = inb(addr);
		pi = (u32 *)pb;
93
		while (count >= 4) {
L
Linus Torvalds 已提交
94 95 96 97 98 99 100 101 102 103
			u32 w;

			w  = (inb(addr) << 24);
			w |= (inb(addr) << 16);
			w |= (inb(addr) << 8);
			w |= (inb(addr) << 0);
			*pi++ = w;
			count -= 4;
		}
		pb = (u8 *)pi;
104
		while (count--)
L
Linus Torvalds 已提交
105 106 107 108
			*pb++ = inb(addr);
	}
}

109
void insw(unsigned long __addr, void *dst, unsigned long count)
L
Linus Torvalds 已提交
110
{
111 112 113
	void __iomem *addr = (void __iomem *) __addr;

	if (count) {
L
Linus Torvalds 已提交
114 115 116
		u16 *ps = dst;
		u32 *pi;

117
		if (((unsigned long)ps) & 0x2) {
L
Linus Torvalds 已提交
118 119 120 121
			*ps++ = le16_to_cpu(inw(addr));
			count--;
		}
		pi = (u32 *)ps;
122
		while (count >= 2) {
L
Linus Torvalds 已提交
123 124 125 126 127 128 129 130
			u32 w;

			w  = (le16_to_cpu(inw(addr)) << 16);
			w |= (le16_to_cpu(inw(addr)) << 0);
			*pi++ = w;
			count -= 2;
		}
		ps = (u16 *)pi;
131
		if (count)
L
Linus Torvalds 已提交
132 133 134 135
			*ps = le16_to_cpu(inw(addr));
	}
}

136
void insl(unsigned long __addr, void *dst, unsigned long count)
L
Linus Torvalds 已提交
137
{
138 139 140 141
	void __iomem *addr = (void __iomem *) __addr;

	if (count) {
		if ((((unsigned long)dst) & 0x3) == 0) {
L
Linus Torvalds 已提交
142
			u32 *pi = dst;
143
			while (count--)
L
Linus Torvalds 已提交
144 145 146 147 148 149
				*pi++ = le32_to_cpu(inl(addr));
		} else {
			u32 l = 0, l2, *pi;
			u16 *ps;
			u8 *pb;

150
			switch (((unsigned long)dst) & 3) {
L
Linus Torvalds 已提交
151 152 153 154 155 156
			case 0x2:
				ps = dst;
				count -= 1;
				l = le32_to_cpu(inl(addr));
				*ps++ = l;
				pi = (u32 *)ps;
157
				while (count--) {
L
Linus Torvalds 已提交
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
					l2 = le32_to_cpu(inl(addr));
					*pi++ = (l << 16) | (l2 >> 16);
					l = l2;
				}
				ps = (u16 *)pi;
				*ps = l;
				break;

			case 0x1:
				pb = dst;
				count -= 1;
				l = le32_to_cpu(inl(addr));
				*pb++ = l >> 24;
				ps = (u16 *)pb;
				*ps++ = ((l >> 8) & 0xffff);
				pi = (u32 *)ps;
174
				while (count--) {
L
Linus Torvalds 已提交
175 176 177 178 179 180 181 182 183 184 185 186 187 188
					l2 = le32_to_cpu(inl(addr));
					*pi++ = (l << 24) | (l2 >> 8);
					l = l2;
				}
				pb = (u8 *)pi;
				*pb = l;
				break;

			case 0x3:
				pb = (u8 *)dst;
				count -= 1;
				l = le32_to_cpu(inl(addr));
				*pb++ = l >> 24;
				pi = (u32 *)pb;
189
				while (count--) {
L
Linus Torvalds 已提交
190 191 192 193 194 195 196 197 198 199 200 201 202 203
					l2 = le32_to_cpu(inl(addr));
					*pi++ = (l << 8) | (l2 >> 24);
					l = l2;
				}
				ps = (u16 *)pi;
				*ps++ = ((l >> 8) & 0xffff);
				pb = (u8 *)ps;
				*pb = l;
				break;
			}
		}
	}
}