Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
io.c
Go to the documentation of this file.
1 /*
2  * Alpha IO and memory functions.
3  */
4 
5 #include <linux/kernel.h>
6 #include <linux/types.h>
7 #include <linux/string.h>
8 #include <linux/module.h>
9 #include <asm/io.h>
10 
11 /* Out-of-line versions of the i/o routines that redirect into the
12  platform-specific version. Note that "platform-specific" may mean
13  "generic", which bumps through the machine vector. */
14 
15 unsigned int
17 {
18  unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
19  mb();
20  return ret;
21 }
22 
23 unsigned int ioread16(void __iomem *addr)
24 {
25  unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
26  mb();
27  return ret;
28 }
29 
30 unsigned int ioread32(void __iomem *addr)
31 {
32  unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
33  mb();
34  return ret;
35 }
36 
37 void iowrite8(u8 b, void __iomem *addr)
38 {
40  mb();
41 }
42 
43 void iowrite16(u16 b, void __iomem *addr)
44 {
46  mb();
47 }
48 
49 void iowrite32(u32 b, void __iomem *addr)
50 {
52  mb();
53 }
54 
61 
62 u8 inb(unsigned long port)
63 {
64  return ioread8(ioport_map(port, 1));
65 }
66 
67 u16 inw(unsigned long port)
68 {
69  return ioread16(ioport_map(port, 2));
70 }
71 
72 u32 inl(unsigned long port)
73 {
74  return ioread32(ioport_map(port, 4));
75 }
76 
77 void outb(u8 b, unsigned long port)
78 {
79  iowrite8(b, ioport_map(port, 1));
80 }
81 
82 void outw(u16 b, unsigned long port)
83 {
84  iowrite16(b, ioport_map(port, 2));
85 }
86 
87 void outl(u32 b, unsigned long port)
88 {
89  iowrite32(b, ioport_map(port, 4));
90 }
91 
98 
99 u8 __raw_readb(const volatile void __iomem *addr)
100 {
101  return IO_CONCAT(__IO_PREFIX,readb)(addr);
102 }
103 
104 u16 __raw_readw(const volatile void __iomem *addr)
105 {
106  return IO_CONCAT(__IO_PREFIX,readw)(addr);
107 }
108 
109 u32 __raw_readl(const volatile void __iomem *addr)
110 {
111  return IO_CONCAT(__IO_PREFIX,readl)(addr);
112 }
113 
114 u64 __raw_readq(const volatile void __iomem *addr)
115 {
116  return IO_CONCAT(__IO_PREFIX,readq)(addr);
117 }
118 
119 void __raw_writeb(u8 b, volatile void __iomem *addr)
120 {
122 }
123 
124 void __raw_writew(u16 b, volatile void __iomem *addr)
125 {
127 }
128 
129 void __raw_writel(u32 b, volatile void __iomem *addr)
130 {
132 }
133 
134 void __raw_writeq(u64 b, volatile void __iomem *addr)
135 {
137 }
138 
147 
148 u8 readb(const volatile void __iomem *addr)
149 {
150  u8 ret = __raw_readb(addr);
151  mb();
152  return ret;
153 }
154 
155 u16 readw(const volatile void __iomem *addr)
156 {
157  u16 ret = __raw_readw(addr);
158  mb();
159  return ret;
160 }
161 
162 u32 readl(const volatile void __iomem *addr)
163 {
164  u32 ret = __raw_readl(addr);
165  mb();
166  return ret;
167 }
168 
169 u64 readq(const volatile void __iomem *addr)
170 {
171  u64 ret = __raw_readq(addr);
172  mb();
173  return ret;
174 }
175 
176 void writeb(u8 b, volatile void __iomem *addr)
177 {
178  __raw_writeb(b, addr);
179  mb();
180 }
181 
182 void writew(u16 b, volatile void __iomem *addr)
183 {
184  __raw_writew(b, addr);
185  mb();
186 }
187 
188 void writel(u32 b, volatile void __iomem *addr)
189 {
190  __raw_writel(b, addr);
191  mb();
192 }
193 
194 void writeq(u64 b, volatile void __iomem *addr)
195 {
196  __raw_writeq(b, addr);
197  mb();
198 }
199 
208 
209 
210 /*
211  * Read COUNT 8-bit bytes from port PORT into memory starting at SRC.
212  */
213 void ioread8_rep(void __iomem *port, void *dst, unsigned long count)
214 {
215  while ((unsigned long)dst & 0x3) {
216  if (!count)
217  return;
218  count--;
219  *(unsigned char *)dst = ioread8(port);
220  dst += 1;
221  }
222 
223  while (count >= 4) {
224  unsigned int w;
225  count -= 4;
226  w = ioread8(port);
227  w |= ioread8(port) << 8;
228  w |= ioread8(port) << 16;
229  w |= ioread8(port) << 24;
230  *(unsigned int *)dst = w;
231  dst += 4;
232  }
233 
234  while (count) {
235  --count;
236  *(unsigned char *)dst = ioread8(port);
237  dst += 1;
238  }
239 }
240 
241 void insb(unsigned long port, void *dst, unsigned long count)
242 {
243  ioread8_rep(ioport_map(port, 1), dst, count);
244 }
245 
248 
249 /*
250  * Read COUNT 16-bit words from port PORT into memory starting at
251  * SRC. SRC must be at least short aligned. This is used by the
252  * IDE driver to read disk sectors. Performance is important, but
253  * the interfaces seems to be slow: just using the inlined version
254  * of the inw() breaks things.
255  */
256 void ioread16_rep(void __iomem *port, void *dst, unsigned long count)
257 {
258  if (unlikely((unsigned long)dst & 0x3)) {
259  if (!count)
260  return;
261  BUG_ON((unsigned long)dst & 0x1);
262  count--;
263  *(unsigned short *)dst = ioread16(port);
264  dst += 2;
265  }
266 
267  while (count >= 2) {
268  unsigned int w;
269  count -= 2;
270  w = ioread16(port);
271  w |= ioread16(port) << 16;
272  *(unsigned int *)dst = w;
273  dst += 4;
274  }
275 
276  if (count) {
277  *(unsigned short*)dst = ioread16(port);
278  }
279 }
280 
281 void insw(unsigned long port, void *dst, unsigned long count)
282 {
283  ioread16_rep(ioport_map(port, 2), dst, count);
284 }
285 
288 
289 
290 /*
291  * Read COUNT 32-bit words from port PORT into memory starting at
292  * SRC. Now works with any alignment in SRC. Performance is important,
293  * but the interfaces seems to be slow: just using the inlined version
294  * of the inl() breaks things.
295  */
296 void ioread32_rep(void __iomem *port, void *dst, unsigned long count)
297 {
298  if (unlikely((unsigned long)dst & 0x3)) {
299  while (count--) {
300  struct S { int x __attribute__((packed)); };
301  ((struct S *)dst)->x = ioread32(port);
302  dst += 4;
303  }
304  } else {
305  /* Buffer 32-bit aligned. */
306  while (count--) {
307  *(unsigned int *)dst = ioread32(port);
308  dst += 4;
309  }
310  }
311 }
312 
313 void insl(unsigned long port, void *dst, unsigned long count)
314 {
315  ioread32_rep(ioport_map(port, 4), dst, count);
316 }
317 
320 
321 
322 /*
323  * Like insb but in the opposite direction.
324  * Don't worry as much about doing aligned memory transfers:
325  * doing byte reads the "slow" way isn't nearly as slow as
326  * doing byte writes the slow way (no r-m-w cycle).
327  */
328 void iowrite8_rep(void __iomem *port, const void *xsrc, unsigned long count)
329 {
330  const unsigned char *src = xsrc;
331  while (count--)
332  iowrite8(*src++, port);
333 }
334 
335 void outsb(unsigned long port, const void *src, unsigned long count)
336 {
337  iowrite8_rep(ioport_map(port, 1), src, count);
338 }
339 
342 
343 
344 /*
345  * Like insw but in the opposite direction. This is used by the IDE
346  * driver to write disk sectors. Performance is important, but the
347  * interfaces seems to be slow: just using the inlined version of the
348  * outw() breaks things.
349  */
350 void iowrite16_rep(void __iomem *port, const void *src, unsigned long count)
351 {
352  if (unlikely((unsigned long)src & 0x3)) {
353  if (!count)
354  return;
355  BUG_ON((unsigned long)src & 0x1);
356  iowrite16(*(unsigned short *)src, port);
357  src += 2;
358  --count;
359  }
360 
361  while (count >= 2) {
362  unsigned int w;
363  count -= 2;
364  w = *(unsigned int *)src;
365  src += 4;
366  iowrite16(w >> 0, port);
367  iowrite16(w >> 16, port);
368  }
369 
370  if (count) {
371  iowrite16(*(unsigned short *)src, port);
372  }
373 }
374 
375 void outsw(unsigned long port, const void *src, unsigned long count)
376 {
377  iowrite16_rep(ioport_map(port, 2), src, count);
378 }
379 
382 
383 
384 /*
385  * Like insl but in the opposite direction. This is used by the IDE
386  * driver to write disk sectors. Works with any alignment in SRC.
387  * Performance is important, but the interfaces seems to be slow:
388  * just using the inlined version of the outl() breaks things.
389  */
390 void iowrite32_rep(void __iomem *port, const void *src, unsigned long count)
391 {
392  if (unlikely((unsigned long)src & 0x3)) {
393  while (count--) {
394  struct S { int x __attribute__((packed)); };
395  iowrite32(((struct S *)src)->x, port);
396  src += 4;
397  }
398  } else {
399  /* Buffer 32-bit aligned. */
400  while (count--) {
401  iowrite32(*(unsigned int *)src, port);
402  src += 4;
403  }
404  }
405 }
406 
407 void outsl(unsigned long port, const void *src, unsigned long count)
408 {
409  iowrite32_rep(ioport_map(port, 4), src, count);
410 }
411 
414 
415 
416 /*
417  * Copy data from IO memory space to "real" memory space.
418  * This needs to be optimized.
419  */
420 void memcpy_fromio(void *to, const volatile void __iomem *from, long count)
421 {
422  /* Optimize co-aligned transfers. Everything else gets handled
423  a byte at a time. */
424 
425  if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
426  count -= 8;
427  do {
428  *(u64 *)to = __raw_readq(from);
429  count -= 8;
430  to += 8;
431  from += 8;
432  } while (count >= 0);
433  count += 8;
434  }
435 
436  if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
437  count -= 4;
438  do {
439  *(u32 *)to = __raw_readl(from);
440  count -= 4;
441  to += 4;
442  from += 4;
443  } while (count >= 0);
444  count += 4;
445  }
446 
447  if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
448  count -= 2;
449  do {
450  *(u16 *)to = __raw_readw(from);
451  count -= 2;
452  to += 2;
453  from += 2;
454  } while (count >= 0);
455  count += 2;
456  }
457 
458  while (count > 0) {
459  *(u8 *) to = __raw_readb(from);
460  count--;
461  to++;
462  from++;
463  }
464  mb();
465 }
466 
468 
469 
470 /*
471  * Copy data from "real" memory space to IO memory space.
472  * This needs to be optimized.
473  */
474 void memcpy_toio(volatile void __iomem *to, const void *from, long count)
475 {
476  /* Optimize co-aligned transfers. Everything else gets handled
477  a byte at a time. */
478  /* FIXME -- align FROM. */
479 
480  if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
481  count -= 8;
482  do {
483  __raw_writeq(*(const u64 *)from, to);
484  count -= 8;
485  to += 8;
486  from += 8;
487  } while (count >= 0);
488  count += 8;
489  }
490 
491  if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
492  count -= 4;
493  do {
494  __raw_writel(*(const u32 *)from, to);
495  count -= 4;
496  to += 4;
497  from += 4;
498  } while (count >= 0);
499  count += 4;
500  }
501 
502  if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
503  count -= 2;
504  do {
505  __raw_writew(*(const u16 *)from, to);
506  count -= 2;
507  to += 2;
508  from += 2;
509  } while (count >= 0);
510  count += 2;
511  }
512 
513  while (count > 0) {
514  __raw_writeb(*(const u8 *) from, to);
515  count--;
516  to++;
517  from++;
518  }
519  mb();
520 }
521 
523 
524 
525 /*
526  * "memset" on IO memory space.
527  */
528 void _memset_c_io(volatile void __iomem *to, unsigned long c, long count)
529 {
530  /* Handle any initial odd byte */
531  if (count > 0 && ((u64)to & 1)) {
532  __raw_writeb(c, to);
533  to++;
534  count--;
535  }
536 
537  /* Handle any initial odd halfword */
538  if (count >= 2 && ((u64)to & 2)) {
539  __raw_writew(c, to);
540  to += 2;
541  count -= 2;
542  }
543 
544  /* Handle any initial odd word */
545  if (count >= 4 && ((u64)to & 4)) {
546  __raw_writel(c, to);
547  to += 4;
548  count -= 4;
549  }
550 
551  /* Handle all full-sized quadwords: we're aligned
552  (or have a small count) */
553  count -= 8;
554  if (count >= 0) {
555  do {
556  __raw_writeq(c, to);
557  to += 8;
558  count -= 8;
559  } while (count >= 0);
560  }
561  count += 8;
562 
563  /* The tail is word-aligned if we still have count >= 4 */
564  if (count >= 4) {
565  __raw_writel(c, to);
566  to += 4;
567  count -= 4;
568  }
569 
570  /* The tail is half-word aligned if we have count >= 2 */
571  if (count >= 2) {
572  __raw_writew(c, to);
573  to += 2;
574  count -= 2;
575  }
576 
577  /* And finally, one last byte.. */
578  if (count) {
579  __raw_writeb(c, to);
580  }
581  mb();
582 }
583 
585 
586 /* A version of memcpy used by the vga console routines to move data around
587  arbitrarily between screen and main memory. */
588 
589 void
590 scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
591 {
592  const u16 __iomem *ios = (const u16 __iomem *) s;
593  u16 __iomem *iod = (u16 __iomem *) d;
594  int s_isio = __is_ioaddr(s);
595  int d_isio = __is_ioaddr(d);
596 
597  if (s_isio) {
598  if (d_isio) {
599  /* FIXME: Should handle unaligned ops and
600  operation widening. */
601 
602  count /= 2;
603  while (count--) {
604  u16 tmp = __raw_readw(ios++);
605  __raw_writew(tmp, iod++);
606  }
607  }
608  else
609  memcpy_fromio(d, ios, count);
610  } else {
611  if (d_isio)
612  memcpy_toio(iod, s, count);
613  else
614  memcpy(d, s, count);
615  }
616 }
617 
619 
620 void __iomem *ioport_map(unsigned long port, unsigned int size)
621 {
622  return IO_CONCAT(__IO_PREFIX,ioportmap) (port);
623 }
624 
626 {
627 }
628