io.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:11k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Alpha IO and memory functions.. Just expand the inlines in the header
  3.  * files..
  4.  */
  5. #include <linux/kernel.h>
  6. #include <linux/types.h>
  7. #include <linux/string.h>
  8. #include <asm/io.h>
  9. u8 _inb(unsigned long addr)
  10. {
  11. return __inb(addr);
  12. }
  13. u16 _inw(unsigned long addr)
  14. {
  15. return __inw(addr);
  16. }
  17. u32 _inl(unsigned long addr)
  18. {
  19. return __inl(addr);
  20. }
  21. void _outb(u8 b, unsigned long addr)
  22. {
  23. __outb(b, addr);
  24. }
  25. void _outw(u16 b, unsigned long addr)
  26. {
  27. __outw(b, addr);
  28. }
  29. void _outl(u32 b, unsigned long addr)
  30. {
  31. __outl(b, addr);
  32. }
  33. u8 ___raw_readb(unsigned long addr)
  34. {
  35. return __readb(addr);
  36. }
  37. u16 ___raw_readw(unsigned long addr)
  38. {
  39. return __readw(addr);
  40. }
  41. u32 ___raw_readl(unsigned long addr)
  42. {
  43. return __readl(addr);
  44. }
  45. u64 ___raw_readq(unsigned long addr)
  46. {
  47. return __readq(addr);
  48. }
  49. u8 _readb(unsigned long addr)
  50. {
  51. unsigned long r = __readb(addr);
  52. mb();
  53. return r;
  54. }
  55. u16 _readw(unsigned long addr)
  56. {
  57. unsigned long r = __readw(addr);
  58. mb();
  59. return r;
  60. }
  61. u32 _readl(unsigned long addr)
  62. {
  63. unsigned long r = __readl(addr);
  64. mb();
  65. return r;
  66. }
  67. u64 _readq(unsigned long addr)
  68. {
  69. unsigned long r = __readq(addr);
  70. mb();
  71. return r;
  72. }
  73. void ___raw_writeb(u8 b, unsigned long addr)
  74. {
  75. __writeb(b, addr);
  76. }
  77. void ___raw_writew(u16 b, unsigned long addr)
  78. {
  79. __writew(b, addr);
  80. }
  81. void ___raw_writel(u32 b, unsigned long addr)
  82. {
  83. __writel(b, addr);
  84. }
  85. void ___raw_writeq(u64 b, unsigned long addr)
  86. {
  87. __writeq(b, addr);
  88. }
  89. void _writeb(u8 b, unsigned long addr)
  90. {
  91. __writeb(b, addr);
  92. mb();
  93. }
  94. void _writew(u16 b, unsigned long addr)
  95. {
  96. __writew(b, addr);
  97. mb();
  98. }
  99. void _writel(u32 b, unsigned long addr)
  100. {
  101. __writel(b, addr);
  102. mb();
  103. }
  104. void _writeq(u64 b, unsigned long addr)
  105. {
  106. __writeq(b, addr);
  107. mb();
  108. }
  109. /*
  110.  * Read COUNT 8-bit bytes from port PORT into memory starting at
  111.  * SRC.
  112.  */
  113. void insb (unsigned long port, void *dst, unsigned long count)
  114. {
  115. while (((unsigned long)dst) & 0x3) {
  116. if (!count)
  117. return;
  118. count--;
  119. *(unsigned char *) dst = inb(port);
  120. ((unsigned char *) dst)++;
  121. }
  122. while (count >= 4) {
  123. unsigned int w;
  124. count -= 4;
  125. w = inb(port);
  126. w |= inb(port) << 8;
  127. w |= inb(port) << 16;
  128. w |= inb(port) << 24;
  129. *(unsigned int *) dst = w;
  130. ((unsigned int *) dst)++;
  131. }
  132. while (count) {
  133. --count;
  134. *(unsigned char *) dst = inb(port);
  135. ((unsigned char *) dst)++;
  136. }
  137. }
  138. /*
  139.  * Read COUNT 16-bit words from port PORT into memory starting at
  140.  * SRC.  SRC must be at least short aligned.  This is used by the
  141.  * IDE driver to read disk sectors.  Performance is important, but
  142.  * the interfaces seems to be slow: just using the inlined version
  143.  * of the inw() breaks things.
  144.  */
  145. void insw (unsigned long port, void *dst, unsigned long count)
  146. {
  147. if (((unsigned long)dst) & 0x3) {
  148. if (((unsigned long)dst) & 0x1) {
  149. panic("insw: memory not short aligned");
  150. }
  151. if (!count)
  152. return;
  153. count--;
  154. *(unsigned short* ) dst = inw(port);
  155. ((unsigned short *) dst)++;
  156. }
  157. while (count >= 2) {
  158. unsigned int w;
  159. count -= 2;
  160. w = inw(port);
  161. w |= inw(port) << 16;
  162. *(unsigned int *) dst = w;
  163. ((unsigned int *) dst)++;
  164. }
  165. if (count) {
  166. *(unsigned short*) dst = inw(port);
  167. }
  168. }
  169. /*
  170.  * Read COUNT 32-bit words from port PORT into memory starting at
  171.  * SRC. Now works with any alignment in SRC. Performance is important,
  172.  * but the interfaces seems to be slow: just using the inlined version
  173.  * of the inl() breaks things.
  174.  */
  175. void insl (unsigned long port, void *dst, unsigned long count)
  176. {
  177. unsigned int l = 0, l2;
  178. if (!count)
  179. return;
  180. switch (((unsigned long) dst) & 0x3)
  181. {
  182.  case 0x00: /* Buffer 32-bit aligned */
  183. while (count--)
  184. {
  185. *(unsigned int *) dst = inl(port);
  186. ((unsigned int *) dst)++;
  187. }
  188. break;
  189. /* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */
  190.  case 0x02: /* Buffer 16-bit aligned */
  191. --count;
  192. l = inl(port);
  193. *(unsigned short *) dst = l;
  194. ((unsigned short *) dst)++;
  195. while (count--)
  196. {
  197. l2 = inl(port);
  198. *(unsigned int *) dst = l >> 16 | l2 << 16;
  199. ((unsigned int *) dst)++;
  200. l = l2;
  201. }
  202. *(unsigned short *) dst = l >> 16;
  203. break;
  204.  case 0x01: /* Buffer 8-bit aligned */
  205. --count;
  206. l = inl(port);
  207. *(unsigned char *) dst = l;
  208. ((unsigned char *) dst)++;
  209. *(unsigned short *) dst = l >> 8;
  210. ((unsigned short *) dst)++;
  211. while (count--)
  212. {
  213. l2 = inl(port);
  214. *(unsigned int *) dst = l >> 24 | l2 << 8;
  215. ((unsigned int *) dst)++;
  216. l = l2;
  217. }
  218. *(unsigned char *) dst = l >> 24;
  219. break;
  220.  case 0x03: /* Buffer 8-bit aligned */
  221. --count;
  222. l = inl(port);
  223. *(unsigned char *) dst = l;
  224. ((unsigned char *) dst)++;
  225. while (count--)
  226. {
  227. l2 = inl(port);
  228. *(unsigned int *) dst = l << 24 | l2 >> 8;
  229. ((unsigned int *) dst)++;
  230. l = l2;
  231. }
  232. *(unsigned short *) dst = l >> 8;
  233. ((unsigned short *) dst)++;
  234. *(unsigned char *) dst = l >> 24;
  235. break;
  236. }
  237. }
  238. /*
  239.  * Like insb but in the opposite direction.
  240.  * Don't worry as much about doing aligned memory transfers:
  241.  * doing byte reads the "slow" way isn't nearly as slow as
  242.  * doing byte writes the slow way (no r-m-w cycle).
  243.  */
  244. void outsb(unsigned long port, const void * src, unsigned long count)
  245. {
  246. while (count) {
  247. count--;
  248. outb(*(char *)src, port);
  249. ((char *) src)++;
  250. }
  251. }
  252. /*
  253.  * Like insw but in the opposite direction.  This is used by the IDE
  254.  * driver to write disk sectors.  Performance is important, but the
  255.  * interfaces seems to be slow: just using the inlined version of the
  256.  * outw() breaks things.
  257.  */
  258. void outsw (unsigned long port, const void *src, unsigned long count)
  259. {
  260. if (((unsigned long)src) & 0x3) {
  261. if (((unsigned long)src) & 0x1) {
  262. panic("outsw: memory not short aligned");
  263. }
  264. outw(*(unsigned short*)src, port);
  265. ((unsigned short *) src)++;
  266. --count;
  267. }
  268. while (count >= 2) {
  269. unsigned int w;
  270. count -= 2;
  271. w = *(unsigned int *) src;
  272. ((unsigned int *) src)++;
  273. outw(w >>  0, port);
  274. outw(w >> 16, port);
  275. }
  276. if (count) {
  277. outw(*(unsigned short *) src, port);
  278. }
  279. }
  280. /*
  281.  * Like insl but in the opposite direction.  This is used by the IDE
  282.  * driver to write disk sectors.  Works with any alignment in SRC.
  283.  *  Performance is important, but the interfaces seems to be slow:
  284.  * just using the inlined version of the outl() breaks things.
  285.  */
  286. void outsl (unsigned long port, const void *src, unsigned long count)
  287. {
  288. unsigned int l = 0, l2;
  289. if (!count)
  290. return;
  291. switch (((unsigned long) src) & 0x3)
  292. {
  293.  case 0x00: /* Buffer 32-bit aligned */
  294. while (count--)
  295. {
  296. outl(*(unsigned int *) src, port);
  297. ((unsigned int *) src)++;
  298. }
  299. break;
  300. /* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */
  301.  case 0x02: /* Buffer 16-bit aligned */
  302. --count;
  303. l = *(unsigned short *) src << 16;
  304. ((unsigned short *) src)++;
  305. while (count--)
  306. {
  307. l2 = *(unsigned int *) src;
  308. ((unsigned int *) src)++;
  309. outl (l >> 16 | l2 << 16, port);
  310. l = l2;
  311. }
  312. l2 = *(unsigned short *) src;
  313. outl (l >> 16 | l2 << 16, port);
  314. break;
  315.  case 0x01: /* Buffer 8-bit aligned */
  316. --count;
  317. l  = *(unsigned char *) src << 8;
  318. ((unsigned char *) src)++;
  319. l |= *(unsigned short *) src << 16;
  320. ((unsigned short *) src)++;
  321. while (count--)
  322. {
  323. l2 = *(unsigned int *) src;
  324. ((unsigned int *) src)++;
  325. outl (l >> 8 | l2 << 24, port);
  326. l = l2;
  327. }
  328. l2 = *(unsigned char *) src;
  329. outl (l >> 8 | l2 << 24, port);
  330. break;
  331.  case 0x03: /* Buffer 8-bit aligned */
  332. --count;
  333. l  = *(unsigned char *) src << 24;
  334. ((unsigned char *) src)++;
  335. while (count--)
  336. {
  337. l2 = *(unsigned int *) src;
  338. ((unsigned int *) src)++;
  339. outl (l >> 24 | l2 << 8, port);
  340. l = l2;
  341. }
  342. l2  = *(unsigned short *) src;
  343. ((unsigned short *) src)++;
  344. l2 |= *(unsigned char *) src << 16;
  345. outl (l >> 24 | l2 << 8, port);
  346. break;
  347. }
  348. }
  349. /*
  350.  * Copy data from IO memory space to "real" memory space.
  351.  * This needs to be optimized.
  352.  */
  353. void _memcpy_fromio(void * to, unsigned long from, long count)
  354. {
  355. /* Optimize co-aligned transfers.  Everything else gets handled
  356.    a byte at a time. */
  357. if (count >= 8 && ((long)to & 7) == (from & 7)) {
  358. count -= 8;
  359. do {
  360. *(u64 *)to = __raw_readq(from);
  361. count -= 8;
  362. to += 8;
  363. from += 8;
  364. } while (count >= 0);
  365. count += 8;
  366. }
  367. if (count >= 4 && ((long)to & 3) == (from & 3)) {
  368. count -= 4;
  369. do {
  370. *(u32 *)to = __raw_readl(from);
  371. count -= 4;
  372. to += 4;
  373. from += 4;
  374. } while (count >= 0);
  375. count += 4;
  376. }
  377. if (count >= 2 && ((long)to & 1) == (from & 1)) {
  378. count -= 2;
  379. do {
  380. *(u16 *)to = __raw_readw(from);
  381. count -= 2;
  382. to += 2;
  383. from += 2;
  384. } while (count >= 0);
  385. count += 2;
  386. }
  387. while (count > 0) {
  388. *(u8 *) to = __raw_readb(from);
  389. count--;
  390. to++;
  391. from++;
  392. }
  393. }
  394. /*
  395.  * Copy data from "real" memory space to IO memory space.
  396.  * This needs to be optimized.
  397.  */
  398. void _memcpy_toio(unsigned long to, const void * from, long count)
  399. {
  400. /* Optimize co-aligned transfers.  Everything else gets handled
  401.    a byte at a time. */
  402. /* FIXME -- align FROM.  */
  403. if (count >= 8 && (to & 7) == ((long)from & 7)) {
  404. count -= 8;
  405. do {
  406. __raw_writeq(*(const u64 *)from, to);
  407. count -= 8;
  408. to += 8;
  409. from += 8;
  410. } while (count >= 0);
  411. count += 8;
  412. }
  413. if (count >= 4 && (to & 3) == ((long)from & 3)) {
  414. count -= 4;
  415. do {
  416. __raw_writel(*(const u32 *)from, to);
  417. count -= 4;
  418. to += 4;
  419. from += 4;
  420. } while (count >= 0);
  421. count += 4;
  422. }
  423. if (count >= 2 && (to & 1) == ((long)from & 1)) {
  424. count -= 2;
  425. do {
  426. __raw_writew(*(const u16 *)from, to);
  427. count -= 2;
  428. to += 2;
  429. from += 2;
  430. } while (count >= 0);
  431. count += 2;
  432. }
  433. while (count > 0) {
  434. __raw_writeb(*(const u8 *) from, to);
  435. count--;
  436. to++;
  437. from++;
  438. }
  439. mb();
  440. }
  441. /*
  442.  * "memset" on IO memory space.
  443.  */
  444. void _memset_c_io(unsigned long to, unsigned long c, long count)
  445. {
  446. /* Handle any initial odd byte */
  447. if (count > 0 && (to & 1)) {
  448. __raw_writeb(c, to);
  449. to++;
  450. count--;
  451. }
  452. /* Handle any initial odd halfword */
  453. if (count >= 2 && (to & 2)) {
  454. __raw_writew(c, to);
  455. to += 2;
  456. count -= 2;
  457. }
  458. /* Handle any initial odd word */
  459. if (count >= 4 && (to & 4)) {
  460. __raw_writel(c, to);
  461. to += 4;
  462. count -= 4;
  463. }
  464. /* Handle all full-sized quadwords: we're aligned
  465.    (or have a small count) */
  466. count -= 8;
  467. if (count >= 0) {
  468. do {
  469. __raw_writeq(c, to);
  470. to += 8;
  471. count -= 8;
  472. } while (count >= 0);
  473. }
  474. count += 8;
  475. /* The tail is word-aligned if we still have count >= 4 */
  476. if (count >= 4) {
  477. __raw_writel(c, to);
  478. to += 4;
  479. count -= 4;
  480. }
  481. /* The tail is half-word aligned if we have count >= 2 */
  482. if (count >= 2) {
  483. __raw_writew(c, to);
  484. to += 2;
  485. count -= 2;
  486. }
  487. /* And finally, one last byte.. */
  488. if (count) {
  489. __raw_writeb(c, to);
  490. }
  491. mb();
  492. }
  493. void
  494. scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
  495. {
  496. if (! __is_ioaddr((unsigned long) s)) {
  497. /* Source is memory.  */
  498. if (! __is_ioaddr((unsigned long) d))
  499. memcpy(d, s, count);
  500. else
  501. memcpy_toio(d, s, count);
  502. } else {
  503. /* Source is screen.  */
  504. if (! __is_ioaddr((unsigned long) d))
  505. memcpy_fromio(d, s, count);
  506. else {
  507. /* FIXME: Should handle unaligned ops and
  508.    operation widening.  */
  509. count /= 2;
  510. while (count--) {
  511. u16 tmp = __raw_readw((unsigned long)(s++));
  512. __raw_writew(tmp, (unsigned long)(d++));
  513. }
  514. }
  515. }
  516. }