PeeCeeI.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * PeeCeeI.c: The emerging standard...
  4. *
  5. * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  6. */
  7. #include <linux/module.h>
  8. #include <asm/io.h>
  9. #include <asm/byteorder.h>
  10. void outsb(unsigned long __addr, const void *src, unsigned long count)
  11. {
  12. void __iomem *addr = (void __iomem *) __addr;
  13. const u8 *p = src;
  14. while (count--)
  15. __raw_writeb(*p++, addr);
  16. }
  17. EXPORT_SYMBOL(outsb);
  18. void outsw(unsigned long __addr, const void *src, unsigned long count)
  19. {
  20. void __iomem *addr = (void __iomem *) __addr;
  21. while (count--) {
  22. __raw_writew(*(u16 *)src, addr);
  23. src += sizeof(u16);
  24. }
  25. }
  26. EXPORT_SYMBOL(outsw);
  27. void outsl(unsigned long __addr, const void *src, unsigned long count)
  28. {
  29. void __iomem *addr = (void __iomem *) __addr;
  30. u32 l, l2;
  31. if (!count)
  32. return;
  33. switch (((unsigned long)src) & 0x3) {
  34. case 0x0:
  35. /* src is naturally aligned */
  36. while (count--) {
  37. __raw_writel(*(u32 *)src, addr);
  38. src += sizeof(u32);
  39. }
  40. break;
  41. case 0x2:
  42. /* 2-byte alignment */
  43. while (count--) {
  44. l = (*(u16 *)src) << 16;
  45. l |= *(u16 *)(src + sizeof(u16));
  46. __raw_writel(l, addr);
  47. src += sizeof(u32);
  48. }
  49. break;
  50. case 0x1:
  51. /* Hold three bytes in l each time, grab a byte from l2 */
  52. l = (*(u8 *)src) << 24;
  53. l |= (*(u16 *)(src + sizeof(u8))) << 8;
  54. src += sizeof(u8) + sizeof(u16);
  55. while (count--) {
  56. l2 = *(u32 *)src;
  57. l |= (l2 >> 24);
  58. __raw_writel(l, addr);
  59. l = l2 << 8;
  60. src += sizeof(u32);
  61. }
  62. break;
  63. case 0x3:
  64. /* Hold a byte in l each time, grab 3 bytes from l2 */
  65. l = (*(u8 *)src) << 24;
  66. src += sizeof(u8);
  67. while (count--) {
  68. l2 = *(u32 *)src;
  69. l |= (l2 >> 8);
  70. __raw_writel(l, addr);
  71. l = l2 << 24;
  72. src += sizeof(u32);
  73. }
  74. break;
  75. }
  76. }
  77. EXPORT_SYMBOL(outsl);
  78. void insb(unsigned long __addr, void *dst, unsigned long count)
  79. {
  80. void __iomem *addr = (void __iomem *) __addr;
  81. if (count) {
  82. u32 *pi;
  83. u8 *pb = dst;
  84. while ((((unsigned long)pb) & 0x3) && count--)
  85. *pb++ = __raw_readb(addr);
  86. pi = (u32 *)pb;
  87. while (count >= 4) {
  88. u32 w;
  89. w = (__raw_readb(addr) << 24);
  90. w |= (__raw_readb(addr) << 16);
  91. w |= (__raw_readb(addr) << 8);
  92. w |= (__raw_readb(addr) << 0);
  93. *pi++ = w;
  94. count -= 4;
  95. }
  96. pb = (u8 *)pi;
  97. while (count--)
  98. *pb++ = __raw_readb(addr);
  99. }
  100. }
  101. EXPORT_SYMBOL(insb);
  102. void insw(unsigned long __addr, void *dst, unsigned long count)
  103. {
  104. void __iomem *addr = (void __iomem *) __addr;
  105. if (count) {
  106. u16 *ps = dst;
  107. u32 *pi;
  108. if (((unsigned long)ps) & 0x2) {
  109. *ps++ = __raw_readw(addr);
  110. count--;
  111. }
  112. pi = (u32 *)ps;
  113. while (count >= 2) {
  114. u32 w;
  115. w = __raw_readw(addr) << 16;
  116. w |= __raw_readw(addr) << 0;
  117. *pi++ = w;
  118. count -= 2;
  119. }
  120. ps = (u16 *)pi;
  121. if (count)
  122. *ps = __raw_readw(addr);
  123. }
  124. }
  125. EXPORT_SYMBOL(insw);
  126. void insl(unsigned long __addr, void *dst, unsigned long count)
  127. {
  128. void __iomem *addr = (void __iomem *) __addr;
  129. if (count) {
  130. if ((((unsigned long)dst) & 0x3) == 0) {
  131. u32 *pi = dst;
  132. while (count--)
  133. *pi++ = __raw_readl(addr);
  134. } else {
  135. u32 l = 0, l2, *pi;
  136. u16 *ps;
  137. u8 *pb;
  138. switch (((unsigned long)dst) & 3) {
  139. case 0x2:
  140. ps = dst;
  141. count -= 1;
  142. l = __raw_readl(addr);
  143. *ps++ = l;
  144. pi = (u32 *)ps;
  145. while (count--) {
  146. l2 = __raw_readl(addr);
  147. *pi++ = (l << 16) | (l2 >> 16);
  148. l = l2;
  149. }
  150. ps = (u16 *)pi;
  151. *ps = l;
  152. break;
  153. case 0x1:
  154. pb = dst;
  155. count -= 1;
  156. l = __raw_readl(addr);
  157. *pb++ = l >> 24;
  158. ps = (u16 *)pb;
  159. *ps++ = ((l >> 8) & 0xffff);
  160. pi = (u32 *)ps;
  161. while (count--) {
  162. l2 = __raw_readl(addr);
  163. *pi++ = (l << 24) | (l2 >> 8);
  164. l = l2;
  165. }
  166. pb = (u8 *)pi;
  167. *pb = l;
  168. break;
  169. case 0x3:
  170. pb = (u8 *)dst;
  171. count -= 1;
  172. l = __raw_readl(addr);
  173. *pb++ = l >> 24;
  174. pi = (u32 *)pb;
  175. while (count--) {
  176. l2 = __raw_readl(addr);
  177. *pi++ = (l << 8) | (l2 >> 24);
  178. l = l2;
  179. }
  180. ps = (u16 *)pi;
  181. *ps++ = ((l >> 8) & 0xffff);
  182. pb = (u8 *)ps;
  183. *pb = l;
  184. break;
  185. }
  186. }
  187. }
  188. }
  189. EXPORT_SYMBOL(insl);