2 * Alpha IO and memory functions.. Just expand the inlines in the header
6 #include <linux/kernel.h>
7 #include <linux/types.h>
8 #include <linux/string.h>
12 u8 _inb(unsigned long addr)
17 u16 _inw(unsigned long addr)
22 u32 _inl(unsigned long addr)
28 void _outb(u8 b, unsigned long addr)
33 void _outw(u16 b, unsigned long addr)
38 void _outl(u32 b, unsigned long addr)
43 u8 ___raw_readb(unsigned long addr)
48 u16 ___raw_readw(unsigned long addr)
53 u32 ___raw_readl(unsigned long addr)
58 u64 ___raw_readq(unsigned long addr)
63 u8 _readb(unsigned long addr)
65 unsigned long r = __readb(addr);
70 u16 _readw(unsigned long addr)
72 unsigned long r = __readw(addr);
77 u32 _readl(unsigned long addr)
79 unsigned long r = __readl(addr);
84 u64 _readq(unsigned long addr)
86 unsigned long r = __readq(addr);
91 void ___raw_writeb(u8 b, unsigned long addr)
96 void ___raw_writew(u16 b, unsigned long addr)
101 void ___raw_writel(u32 b, unsigned long addr)
106 void ___raw_writeq(u64 b, unsigned long addr)
111 void _writeb(u8 b, unsigned long addr)
117 void _writew(u16 b, unsigned long addr)
123 void _writel(u32 b, unsigned long addr)
129 void _writeq(u64 b, unsigned long addr)
136 * Read COUNT 8-bit bytes from port PORT into memory starting at
139 void insb (unsigned long port, void *dst, unsigned long count)
141 while (((unsigned long)dst) & 0x3) {
145 *(unsigned char *) dst = inb(port);
154 w |= inb(port) << 16;
155 w |= inb(port) << 24;
156 *(unsigned int *) dst = w;
162 *(unsigned char *) dst = inb(port);
169 * Read COUNT 16-bit words from port PORT into memory starting at
170 * SRC. SRC must be at least short aligned. This is used by the
171 * IDE driver to read disk sectors. Performance is important, but
172 * the interfaces seems to be slow: just using the inlined version
173 * of the inw() breaks things.
175 void insw (unsigned long port, void *dst, unsigned long count)
177 if (((unsigned long)dst) & 0x3) {
178 if (((unsigned long)dst) & 0x1) {
179 panic("insw: memory not short aligned");
184 *(unsigned short *) dst = inw(port);
192 w |= inw(port) << 16;
193 *(unsigned int *) dst = w;
198 *(unsigned short*) dst = inw(port);
204 * Read COUNT 32-bit words from port PORT into memory starting at
205 * SRC. Now works with any alignment in SRC. Performance is important,
206 * but the interfaces seems to be slow: just using the inlined version
207 * of the inl() breaks things.
209 void insl (unsigned long port, void *dst, unsigned long count)
211 unsigned int l = 0, l2;
216 switch (((unsigned long) dst) & 0x3)
218 case 0x00: /* Buffer 32-bit aligned */
221 *(unsigned int *) dst = inl(port);
226 /* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */
228 case 0x02: /* Buffer 16-bit aligned */
232 *(unsigned short *) dst = l;
238 *(unsigned int *) dst = l >> 16 | l2 << 16;
242 *(unsigned short *) dst = l >> 16;
245 case 0x01: /* Buffer 8-bit aligned */
249 *(unsigned char *) dst = l;
251 *(unsigned short *) dst = l >> 8;
256 *(unsigned int *) dst = l >> 24 | l2 << 8;
260 *(unsigned char *) dst = l >> 24;
263 case 0x03: /* Buffer 8-bit aligned */
267 *(unsigned char *) dst = l;
272 *(unsigned int *) dst = l << 24 | l2 >> 8;
276 *(unsigned short *) dst = l >> 8;
278 *(unsigned char *) dst = l >> 24;
285 * Like insb but in the opposite direction.
286 * Don't worry as much about doing aligned memory transfers:
287 * doing byte reads the "slow" way isn't nearly as slow as
288 * doing byte writes the slow way (no r-m-w cycle).
290 void outsb(unsigned long port, const void * src, unsigned long count)
294 outb(*(char *)src, port);
300 * Like insw but in the opposite direction. This is used by the IDE
301 * driver to write disk sectors. Performance is important, but the
302 * interfaces seems to be slow: just using the inlined version of the
303 * outw() breaks things.
305 void outsw (unsigned long port, const void *src, unsigned long count)
307 if (((unsigned long)src) & 0x3) {
308 if (((unsigned long)src) & 0x1) {
309 panic("outsw: memory not short aligned");
311 outw(*(unsigned short*)src, port);
319 w = *(unsigned int *) src;
326 outw(*(unsigned short *) src, port);
332 * Like insl but in the opposite direction. This is used by the IDE
333 * driver to write disk sectors. Works with any alignment in SRC.
334 * Performance is important, but the interfaces seems to be slow:
335 * just using the inlined version of the outl() breaks things.
337 void outsl (unsigned long port, const void *src, unsigned long count)
339 unsigned int l = 0, l2;
344 switch (((unsigned long) src) & 0x3)
346 case 0x00: /* Buffer 32-bit aligned */
349 outl(*(unsigned int *) src, port);
354 case 0x02: /* Buffer 16-bit aligned */
357 l = *(unsigned short *) src << 16;
362 l2 = *(unsigned int *) src;
364 outl (l >> 16 | l2 << 16, port);
367 l2 = *(unsigned short *) src;
368 outl (l >> 16 | l2 << 16, port);
371 case 0x01: /* Buffer 8-bit aligned */
374 l = *(unsigned char *) src << 8;
376 l |= *(unsigned short *) src << 16;
380 l2 = *(unsigned int *) src;
382 outl (l >> 8 | l2 << 24, port);
385 l2 = *(unsigned char *) src;
386 outl (l >> 8 | l2 << 24, port);
389 case 0x03: /* Buffer 8-bit aligned */
392 l = *(unsigned char *) src << 24;
396 l2 = *(unsigned int *) src;
398 outl (l >> 24 | l2 << 8, port);
401 l2 = *(unsigned short *) src;
403 l2 |= *(unsigned char *) src << 16;
404 outl (l >> 24 | l2 << 8, port);
411 * Copy data from IO memory space to "real" memory space.
412 * This needs to be optimized.
414 void _memcpy_fromio(void * to, unsigned long from, long count)
416 /* Optimize co-aligned transfers. Everything else gets handled
419 if (count >= 8 && ((unsigned long)to & 7) == (from & 7)) {
422 *(u64 *)to = __raw_readq(from);
426 } while (count >= 0);
430 if (count >= 4 && ((unsigned long)to & 3) == (from & 3)) {
433 *(u32 *)to = __raw_readl(from);
437 } while (count >= 0);
441 if (count >= 2 && ((unsigned long)to & 1) == (from & 1)) {
444 *(u16 *)to = __raw_readw(from);
448 } while (count >= 0);
453 *(u8 *) to = __raw_readb(from);
461 * Copy data from "real" memory space to IO memory space.
462 * This needs to be optimized.
464 void _memcpy_toio(unsigned long to, const void * from, long count)
466 /* Optimize co-aligned transfers. Everything else gets handled
468 /* FIXME -- align FROM. */
470 if (count >= 8 && (to & 7) == ((unsigned long)from & 7)) {
473 __raw_writeq(*(const u64 *)from, to);
477 } while (count >= 0);
481 if (count >= 4 && (to & 3) == ((unsigned long)from & 3)) {
484 __raw_writel(*(const u32 *)from, to);
488 } while (count >= 0);
492 if (count >= 2 && (to & 1) == ((unsigned long)from & 1)) {
495 __raw_writew(*(const u16 *)from, to);
499 } while (count >= 0);
504 __raw_writeb(*(const u8 *) from, to);
513 * "memset" on IO memory space.
515 void _memset_c_io(unsigned long to, unsigned long c, long count)
517 /* Handle any initial odd byte */
518 if (count > 0 && (to & 1)) {
524 /* Handle any initial odd halfword */
525 if (count >= 2 && (to & 2)) {
531 /* Handle any initial odd word */
532 if (count >= 4 && (to & 4)) {
538 /* Handle all full-sized quadwords: we're aligned
539 (or have a small count) */
546 } while (count >= 0);
550 /* The tail is word-aligned if we still have count >= 4 */
557 /* The tail is half-word aligned if we have count >= 2 */
564 /* And finally, one last byte.. */
572 scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
574 if (! __is_ioaddr((unsigned long) s)) {
575 /* Source is memory. */
576 if (! __is_ioaddr((unsigned long) d))
579 memcpy_toio(d, s, count);
581 /* Source is screen. */
582 if (! __is_ioaddr((unsigned long) d))
583 memcpy_fromio(d, s, count);
585 /* FIXME: Should handle unaligned ops and
586 operation widening. */
589 u16 tmp = __raw_readw((unsigned long)(s++));
590 __raw_writew(tmp, (unsigned long)(d++));