io.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/arm/mach-ebsa110/isamem.c
  3.  *
  4.  *  Copyright (C) 2001 Russell King
  5.  *
  6.  * Perform "ISA" memory and IO accesses.  The EBSA110 has some "peculiarities"
  7.  * in the way it handles accesses to odd IO ports on 16-bit devices.  These
  8.  * devices have their D0-D15 lines connected to the processors D0-D15 lines.
  9.  * Since they expect all byte IO operations to be performed on D0-D7, and the
  10.  * StrongARM expects to transfer the byte to these odd addresses on D8-D15,
  11.  * we must use a trick to get the required behaviour.
  12.  *
  13.  * The trick employed here is to use long word stores to odd address -1.  The
  14.  * glue logic picks this up as a "trick" access, and asserts the LSB of the
  15.  * peripherals address bus, thereby accessing the odd IO port.  Meanwhile, the
  16.  * StrongARM transfers its data on D0-D7 as expected.
  17.  *
  18.  * Things get more interesting on the pass-1 EBSA110 - the PCMCIA controller
  19.  * wiring was screwed in such a way that it had limited memory space access.
  20.  * Luckily, the work-around for this is not too horrible.  See
  21.  * __isamem_convert_addr for the details.
  22.  */
  23. #include <linux/module.h>
  24. #include <linux/kernel.h>
  25. #include <linux/types.h>
  26. #include <asm/io.h>
  27. #include <asm/page.h>
  28. static u32 __isamem_convert_addr(void *addr)
  29. {
  30. u32 ret, a = (u32) addr;
  31. /*
  32.  * The PCMCIA controller is wired up as follows:
  33.  *        +---------+---------+---------+---------+---------+---------+
  34.  * PCMCIA | 2 2 2 2 | 1 1 1 1 | 1 1 1 1 | 1 1     |         |         |
  35.  *        | 3 2 1 0 | 9 8 7 6 | 5 4 3 2 | 1 0 9 8 | 7 6 5 4 | 3 2 1 0 |
  36.  *        +---------+---------+---------+---------+---------+---------+
  37.  *  CPU   | 2 2 2 2 | 2 1 1 1 | 1 1 1 1 | 1 1 1   |         |         |
  38.  *        | 4 3 2 1 | 0 9 9 8 | 7 6 5 4 | 3 2 0 9 | 8 7 6 5 | 4 3 2 x |
  39.  *        +---------+---------+---------+---------+---------+---------+
  40.  *
  41.  * This means that we can access PCMCIA regions as follows:
  42.  * 0x*10000 -> 0x*1ffff
  43.  * 0x*70000 -> 0x*7ffff
  44.  * 0x*90000 -> 0x*9ffff
  45.  * 0x*f0000 -> 0x*fffff
  46.  */
  47. ret  = (a & 0xf803fe) << 1;
  48. ret |= (a & 0x03fc00) << 2;
  49. ret += 0xe8000000;
  50. if ((a & 0x20000) == (a & 0x40000) >> 1)
  51. return ret;
  52. BUG();
  53. return 0;
  54. }
  55. /*
  56.  * read[bwl] and write[bwl]
  57.  */
  58. u8 __readb(void *addr)
  59. {
  60. u32 ret, a = __isamem_convert_addr(addr);
  61. if ((int)addr & 1)
  62. ret = __arch_getl(a);
  63. else
  64. ret = __arch_getb(a);
  65. return ret;
  66. }
  67. u16 __readw(void *addr)
  68. {
  69. u32 a = __isamem_convert_addr(addr);
  70. if ((int)addr & 1)
  71. BUG();
  72. return __arch_getw(a);
  73. }
  74. u32 __readl(void *addr)
  75. {
  76. u32 ret, a = __isamem_convert_addr(addr);
  77. if ((int)addr & 3)
  78. BUG();
  79. ret = __arch_getw(a);
  80. ret |= __arch_getw(a + 4) << 16;
  81. return ret;
  82. }
  83. EXPORT_SYMBOL(__readb);
  84. EXPORT_SYMBOL(__readw);
  85. EXPORT_SYMBOL(__readl);
  86. void __writeb(u8 val, void *addr)
  87. {
  88. u32 a = __isamem_convert_addr(addr);
  89. if ((int)addr & 1)
  90. __arch_putl(val, a);
  91. else
  92. __arch_putb(val, a);
  93. }
  94. void __writew(u16 val, void *addr)
  95. {
  96. u32 a = __isamem_convert_addr(addr);
  97. if ((int)addr & 1)
  98. BUG();
  99. __arch_putw(val, a);
  100. }
  101. void __writel(u32 val, void *addr)
  102. {
  103. u32 a = __isamem_convert_addr(addr);
  104. if ((int)addr & 3)
  105. BUG();
  106. __arch_putw(val, a);
  107. __arch_putw(val >> 16, a + 4);
  108. }
  109. EXPORT_SYMBOL(__writeb);
  110. EXPORT_SYMBOL(__writew);
  111. EXPORT_SYMBOL(__writel);
  112. #define SUPERIO_PORT(p) 
  113. (((p) >> 3) == (0x3f8 >> 3) || 
  114.  ((p) >> 3) == (0x2f8 >> 3) || 
  115.  ((p) >> 3) == (0x378 >> 3))
  116. /*
  117.  * We're addressing an 8 or 16-bit peripheral which tranfers
  118.  * odd addresses on the low ISA byte lane.
  119.  */
  120. u8 __inb8(unsigned int port)
  121. {
  122. u32 ret;
  123. /*
  124.  * The SuperIO registers use sane addressing techniques...
  125.  */
  126. if (SUPERIO_PORT(port))
  127. ret = __arch_getb(ISAIO_BASE + (port << 2));
  128. else {
  129. u32 a = ISAIO_BASE + ((port & ~1) << 1);
  130. /*
  131.  * Shame nothing else does
  132.  */
  133. if (port & 1)
  134. ret = __arch_getl(a);
  135. else
  136. ret = __arch_getb(a);
  137. }
  138. return ret;
  139. }
  140. /*
  141.  * We're addressing a 16-bit peripheral which transfers odd
  142.  * addresses on the high ISA byte lane.
  143.  */
  144. u8 __inb16(unsigned int port)
  145. {
  146. u32 ret;
  147. /*
  148.  * The SuperIO registers use sane addressing techniques...
  149.  */
  150. if (SUPERIO_PORT(port))
  151. ret = __arch_getb(ISAIO_BASE + (port << 2));
  152. else {
  153. u32 a = ISAIO_BASE + ((port & ~1) << 1);
  154. /*
  155.  * Shame nothing else does
  156.  */
  157. ret = __arch_getb(a + (port & 1));
  158. }
  159. return ret;
  160. }
  161. u16 __inw(unsigned int port)
  162. {
  163. u32 ret;
  164. /*
  165.  * The SuperIO registers use sane addressing techniques...
  166.  */
  167. if (SUPERIO_PORT(port) || port & 1)
  168. ret = __arch_getw(ISAIO_BASE + (port << 2));
  169. else {
  170. u32 a = ISAIO_BASE + (port << 1);
  171. /*
  172.  * Shame nothing else does
  173.  */
  174. if (port & 1)
  175. BUG();
  176. ret = __arch_getw(a);
  177. }
  178. return ret;
  179. }
  180. /*
  181.  * Fake a 32-bit read with two 16-bit reads.  Needed for 3c589.
  182.  */
  183. u32 __inl(unsigned int port)
  184. {
  185. u32 a;
  186. if (SUPERIO_PORT(port) || port & 3)
  187. BUG();
  188. a = ISAIO_BASE + (port << 1);
  189. return __arch_getw(a) | __arch_getw(a + 4) << 16;
  190. }
  191. EXPORT_SYMBOL(__inb8);
  192. EXPORT_SYMBOL(__inb16);
  193. EXPORT_SYMBOL(__inw);
  194. EXPORT_SYMBOL(__inl);
  195. void __outb8(u8 val, unsigned int port)
  196. {
  197. /*
  198.  * The SuperIO registers use sane addressing techniques...
  199.  */
  200. if (SUPERIO_PORT(port))
  201. __arch_putb(val, ISAIO_BASE + (port << 2));
  202. else {
  203. u32 a = ISAIO_BASE + ((port & ~1) << 1);
  204. /*
  205.  * Shame nothing else does
  206.  */
  207. if (port & 1)
  208. __arch_putl(val, a);
  209. else
  210. __arch_putb(val, a);
  211. }
  212. }
  213. void __outb16(u8 val, unsigned int port)
  214. {
  215. /*
  216.  * The SuperIO registers use sane addressing techniques...
  217.  */
  218. if (SUPERIO_PORT(port))
  219. __arch_putb(val, ISAIO_BASE + (port << 2));
  220. else {
  221. u32 a = ISAIO_BASE + ((port & ~1) << 1);
  222. /*
  223.  * Shame nothing else does
  224.  */
  225. __arch_putb(val, a + (port & 1));
  226. }
  227. }
  228. void __outw(u16 val, unsigned int port)
  229. {
  230. u32 off;
  231. /*
  232.  * The SuperIO registers use sane addressing techniques...
  233.  */
  234. if (SUPERIO_PORT(port))
  235. off = port << 2;
  236. else {
  237. off = port << 1;
  238. if (port & 1)
  239. BUG();
  240. }
  241. __arch_putw(val, ISAIO_BASE + off);
  242. }
  243. void __outl(u32 val, unsigned int port)
  244. {
  245. BUG();
  246. }
  247. EXPORT_SYMBOL(__outb8);
  248. EXPORT_SYMBOL(__outb16);
  249. EXPORT_SYMBOL(__outw);
  250. EXPORT_SYMBOL(__outl);
  251. extern void __arch_writesb(unsigned long virt, const void *from, int len);
  252. extern void __arch_writesw(unsigned long virt, const void *from, int len);
  253. extern void __arch_writesl(unsigned long virt, const void *from, int len);
  254. extern void __arch_readsb(unsigned long virt, void *from, int len);
  255. extern void __arch_readsw(unsigned long virt, void *from, int len);
  256. extern void __arch_readsl(unsigned long virt, void *from, int len);
  257. void outsb(unsigned int port, const void *from, int len)
  258. {
  259. u32 off;
  260. if (SUPERIO_PORT(port))
  261. off = port << 2;
  262. else {
  263. off = (port & ~1) << 1;
  264. if (port & 1)
  265. BUG();
  266. }
  267. __raw_writesb(ISAIO_BASE + off, from, len);
  268. }
  269. void insb(unsigned int port, void *from, int len)
  270. {
  271. u32 off;
  272. if (SUPERIO_PORT(port))
  273. off = port << 2;
  274. else {
  275. off = (port & ~1) << 1;
  276. if (port & 1)
  277. BUG();
  278. }
  279. __raw_readsb(ISAIO_BASE + off, from, len);
  280. }
  281. EXPORT_SYMBOL(outsb);
  282. EXPORT_SYMBOL(insb);
  283. void outsw(unsigned int port, const void *from, int len)
  284. {
  285. u32 off;
  286. if (SUPERIO_PORT(port))
  287. off = port << 2;
  288. else {
  289. off = (port & ~1) << 1;
  290. if (port & 1)
  291. BUG();
  292. }
  293. __raw_writesw(ISAIO_BASE + off, from, len);
  294. }
  295. void insw(unsigned int port, void *from, int len)
  296. {
  297. u32 off;
  298. if (SUPERIO_PORT(port))
  299. off = port << 2;
  300. else {
  301. off = (port & ~1) << 1;
  302. if (port & 1)
  303. BUG();
  304. }
  305. __raw_readsw(ISAIO_BASE + off, from, len);
  306. }
  307. EXPORT_SYMBOL(outsw);
  308. EXPORT_SYMBOL(insw);
  309. /*
  310.  * We implement these as 16-bit insw/outsw, mainly for
  311.  * 3c589 cards.
  312.  */
  313. void outsl(unsigned int port, const void *from, int len)
  314. {
  315. u32 off = port << 1;
  316. if (SUPERIO_PORT(port) || port & 3)
  317. BUG();
  318. __raw_writesw(ISAIO_BASE + off, from, len << 1);
  319. }
  320. void insl(unsigned int port, void *from, int len)
  321. {
  322. u32 off = port << 1;
  323. if (SUPERIO_PORT(port) || port & 3)
  324. BUG();
  325. __raw_readsw(ISAIO_BASE + off, from, len << 1);
  326. }
  327. EXPORT_SYMBOL(outsl);
  328. EXPORT_SYMBOL(insl);