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 unsigned int _inb(unsigned long addr
)
17 unsigned int _inw(unsigned long addr
)
22 unsigned int _inl(unsigned long addr
)
28 void _outb(unsigned char b
, unsigned long addr
)
33 void _outw(unsigned short b
, unsigned long addr
)
38 void _outl(unsigned int b
, unsigned long addr
)
43 unsigned long ___raw_readb(unsigned long addr
)
48 unsigned long ___raw_readw(unsigned long addr
)
53 unsigned long ___raw_readl(unsigned long addr
)
58 unsigned long ___raw_readq(unsigned long addr
)
63 unsigned long _readb(unsigned long addr
)
65 unsigned long r
= __readb(addr
);
70 unsigned long _readw(unsigned long addr
)
72 unsigned long r
= __readw(addr
);
77 unsigned long _readl(unsigned long addr
)
79 unsigned long r
= __readl(addr
);
84 unsigned long _readq(unsigned long addr
)
86 unsigned long r
= __readq(addr
);
91 void ___raw_writeb(unsigned char b
, unsigned long addr
)
96 void ___raw_writew(unsigned short b
, unsigned long addr
)
101 void ___raw_writel(unsigned int b
, unsigned long addr
)
106 void ___raw_writeq(unsigned long b
, unsigned long addr
)
111 void _writeb(unsigned char b
, unsigned long addr
)
117 void _writew(unsigned short b
, unsigned long addr
)
123 void _writel(unsigned int b
, unsigned long addr
)
129 void _writeq(unsigned long 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
);
146 ((unsigned char *) dst
)++;
154 w
|= inb(port
) << 16;
155 w
|= inb(port
) << 24;
156 *(unsigned int *) dst
= w
;
157 ((unsigned int *) dst
)++;
162 *(unsigned char *) dst
= inb(port
);
163 ((unsigned char *) dst
)++;
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
);
185 ((unsigned short *) dst
)++;
192 w
|= inw(port
) << 16;
193 *(unsigned int *) dst
= w
;
194 ((unsigned int *) dst
)++;
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
);
222 ((unsigned int *) dst
)++;
226 /* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */
228 case 0x02: /* Buffer 16-bit aligned */
232 *(unsigned short *) dst
= l
;
233 ((unsigned short *) dst
)++;
238 *(unsigned int *) dst
= l
>> 16 | l2
<< 16;
239 ((unsigned int *) dst
)++;
242 *(unsigned short *) dst
= l
>> 16;
244 case 0x01: /* Buffer 8-bit aligned */
248 *(unsigned char *) dst
= l
;
249 ((unsigned char *) dst
)++;
250 *(unsigned short *) dst
= l
>> 8;
251 ((unsigned short *) dst
)++;
255 *(unsigned int *) dst
= l
>> 24 | l2
<< 8;
256 ((unsigned int *) dst
)++;
259 *(unsigned char *) dst
= l
>> 24;
261 case 0x03: /* Buffer 8-bit aligned */
265 *(unsigned char *) dst
= l
;
266 ((unsigned char *) dst
)++;
270 *(unsigned int *) dst
= l
<< 24 | l2
>> 8;
271 ((unsigned int *) dst
)++;
274 *(unsigned short *) dst
= l
>> 8;
275 ((unsigned short *) dst
)++;
276 *(unsigned char *) dst
= l
>> 24;
283 * Like insb but in the opposite direction.
284 * Don't worry as much about doing aligned memory transfers:
285 * doing byte reads the "slow" way isn't nearly as slow as
286 * doing byte writes the slow way (no r-m-w cycle).
288 void outsb(unsigned long port
, const void * src
, unsigned long count
)
292 outb(*(char *)src
, port
);
298 * Like insw but in the opposite direction. This is used by the IDE
299 * driver to write disk sectors. Performance is important, but the
300 * interfaces seems to be slow: just using the inlined version of the
301 * outw() breaks things.
303 void outsw (unsigned long port
, const void *src
, unsigned long count
)
305 if (((unsigned long)src
) & 0x3) {
306 if (((unsigned long)src
) & 0x1) {
307 panic("outsw: memory not short aligned");
309 outw(*(unsigned short*)src
, port
);
310 ((unsigned short *) src
)++;
317 w
= *(unsigned int *) src
;
318 ((unsigned int *) src
)++;
324 outw(*(unsigned short *) src
, port
);
330 * Like insl but in the opposite direction. This is used by the IDE
331 * driver to write disk sectors. Works with any alignment in SRC.
332 * Performance is important, but the interfaces seems to be slow:
333 * just using the inlined version of the outl() breaks things.
335 void outsl (unsigned long port
, const void *src
, unsigned long count
)
337 unsigned int l
= 0, l2
;
342 switch (((unsigned long) src
) & 0x3)
344 case 0x00: /* Buffer 32-bit aligned */
347 outl(*(unsigned int *) src
, port
);
348 ((unsigned int *) src
)++;
352 /* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */
354 case 0x02: /* Buffer 16-bit aligned */
357 l
= *(unsigned short *) src
<< 16;
358 ((unsigned short *) src
)++;
362 l2
= *(unsigned int *) src
;
363 ((unsigned int *) src
)++;
364 outl (l
>> 16 | l2
<< 16, port
);
367 l2
= *(unsigned short *) src
;
368 outl (l
>> 16 | l2
<< 16, port
);
370 case 0x01: /* Buffer 8-bit aligned */
373 l
= *(unsigned char *) src
<< 8;
374 ((unsigned char *) src
)++;
375 l
|= *(unsigned short *) src
<< 16;
376 ((unsigned short *) src
)++;
379 l2
= *(unsigned int *) src
;
380 ((unsigned int *) src
)++;
381 outl (l
>> 8 | l2
<< 24, port
);
384 l2
= *(unsigned char *) src
;
385 outl (l
>> 8 | l2
<< 24, port
);
387 case 0x03: /* Buffer 8-bit aligned */
390 l
= *(unsigned char *) src
<< 24;
391 ((unsigned char *) src
)++;
394 l2
= *(unsigned int *) src
;
395 ((unsigned int *) src
)++;
396 outl (l
>> 24 | l2
<< 8, port
);
399 l2
= *(unsigned short *) src
;
400 ((unsigned short *) src
)++;
401 l2
|= *(unsigned char *) src
<< 16;
402 outl (l
>> 24 | l2
<< 8, port
);
409 * Copy data from IO memory space to "real" memory space.
410 * This needs to be optimized.
412 void _memcpy_fromio(void * to
, unsigned long from
, long count
)
414 /* Optimize co-aligned transfers. Everything else gets handled
417 if (count
>= 8 && ((long)to
& 7) == (from
& 7)) {
420 *(u64
*)to
= __raw_readq(from
);
424 } while (count
>= 0);
428 if (count
>= 4 && ((long)to
& 3) == (from
& 3)) {
431 *(u32
*)to
= __raw_readl(from
);
435 } while (count
>= 0);
439 if (count
>= 2 && ((long)to
& 1) == (from
& 1)) {
442 *(u16
*)to
= __raw_readw(from
);
446 } while (count
>= 0);
451 *(u8
*) to
= __raw_readb(from
);
459 * Copy data from "real" memory space to IO memory space.
460 * This needs to be optimized.
462 void _memcpy_toio(unsigned long to
, const void * from
, long count
)
464 /* Optimize co-aligned transfers. Everything else gets handled
466 /* FIXME -- align FROM. */
468 if (count
>= 8 && (to
& 7) == ((long)from
& 7)) {
471 __raw_writeq(*(const u64
*)from
, to
);
475 } while (count
>= 0);
479 if (count
>= 4 && (to
& 3) == ((long)from
& 3)) {
482 __raw_writel(*(const u32
*)from
, to
);
486 } while (count
>= 0);
490 if (count
>= 2 && (to
& 1) == ((long)from
& 1)) {
493 __raw_writew(*(const u16
*)from
, to
);
497 } while (count
>= 0);
502 __raw_writeb(*(const u8
*) from
, to
);
511 * "memset" on IO memory space.
513 void _memset_c_io(unsigned long to
, unsigned long c
, long count
)
515 /* Handle any initial odd byte */
516 if (count
> 0 && (to
& 1)) {
522 /* Handle any initial odd halfword */
523 if (count
>= 2 && (to
& 2)) {
529 /* Handle any initial odd word */
530 if (count
>= 4 && (to
& 4)) {
536 /* Handle all full-sized quadwords: we're aligned
537 (or have a small count) */
544 } while (count
>= 0);
548 /* The tail is word-aligned if we still have count >= 4 */
555 /* The tail is half-word aligned if we have count >= 2 */
562 /* And finally, one last byte.. */
570 scr_memcpyw(u16
*d
, const u16
*s
, unsigned int count
)
572 if (! __is_ioaddr((unsigned long) s
)) {
573 /* Source is memory. */
574 if (! __is_ioaddr((unsigned long) d
))
577 memcpy_toio(d
, s
, count
);
579 /* Source is screen. */
580 if (! __is_ioaddr((unsigned long) d
))
581 memcpy_fromio(d
, s
, count
);
583 /* FIXME: Should handle unaligned ops and
584 operation widening. */
587 u16 tmp
= __raw_readw((unsigned long)(s
++));
588 __raw_writew(tmp
, (unsigned long)(d
++));