patch-2.1.80 linux/arch/arm/lib/io-acorn.S
Next file: linux/arch/arm/lib/io-ebsa110.S
Previous file: linux/arch/arm/lib/getconstants.h
Back to the patch index
Back to the overall index
- Lines: 215
- Date:
Tue Jan 20 16:39:41 1998
- Orig file:
v2.1.79/linux/arch/arm/lib/io-acorn.S
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/io-acorn.S linux/arch/arm/lib/io-acorn.S
@@ -0,0 +1,214 @@
+/*
+ * linux/arch/arm/lib/io.S
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ */
+#include <linux/autoconf.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+ .text
+ .align
+
+#define OUT(reg) \
+ mov r8, reg, lsl $16 ;\
+ orr r8, r8, r8, lsr $16 ;\
+ str r8, [r3, r0, lsl $2] ;\
+ mov r8, reg, lsr $16 ;\
+ orr r8, r8, r8, lsl $16 ;\
+ str r8, [r3, r0, lsl $2]
+
+#define IN(reg) \
+ ldr reg, [r0] ;\
+ and reg, reg, ip ;\
+ ldr lr, [r0] ;\
+ orr reg, reg, lr, lsl $16
+
+ .equ pcio_base_high, PCIO_BASE & 0xff000000
+ .equ pcio_base_low, PCIO_BASE & 0x00ff0000
+ .equ io_base_high, IO_BASE & 0xff000000
+ .equ io_base_low, IO_BASE & 0x00ff0000
+
+ .equ addr_io_diff_hi, pcio_base_high - io_base_high
+ .equ addr_io_diff_lo, pcio_base_low - io_base_low
+
+ .macro addr reg, off
+ tst \off, #0x80000000
+ .if addr_io_diff_hi
+ movne \reg, #IO_BASE
+ moveq \reg, #pcio_base_high
+ .if pcio_base_low
+ addeq \reg, \reg, #pcio_base_low
+ .endif
+ .else
+ mov \reg, #IO_BASE
+ addeq \reg, \reg, #addr_io_diff_lo
+ .endif
+ .endm
+
+@ Purpose: read a block of data from a hardware register to memory.
+@ Proto : insw(int from_port, void *to, int len_in_words);
+@ Proto : inswb(int from_port, void *to, int len_in_bytes);
+@ Notes : increment to
+
+ENTRY(insw)
+ mov r2, r2, lsl#1
+ENTRY(inswb)
+ mov ip, sp
+ stmfd sp!, {r4 - r10 ,fp ,ip ,lr ,pc}
+ sub fp, ip, #4
+ addr r3, r0
+ add r0, r3, r0, lsl #2
+ tst r1, #3
+ beq Linswok
+ tst r1, #1
+ bne Linsw_notaligned
+ cmp r2, #1
+ ldrge r4, [r0]
+ strgeb r4, [r1], #1
+ movgt r4, r4, LSR#8
+ strgtb r4, [r1], #1
+ ldmleea fp, {r4 - r10, fp, sp, pc}^
+ sub r2, r2, #2
+Linswok: mov ip, #0xFF
+ orr ip, ip, ip, lsl #8
+Linswlp: subs r2, r2, #64
+ bmi Linsw_toosmall
+ IN(r3)
+ IN(r4)
+ IN(r5)
+ IN(r6)
+ IN(r7)
+ IN(r8)
+ IN(r9)
+ IN(r10)
+ stmia r1!, {r3 - r10}
+ IN(r3)
+ IN(r4)
+ IN(r5)
+ IN(r6)
+ IN(r7)
+ IN(r8)
+ IN(r9)
+ IN(r10)
+ stmia r1!, {r3 - r10}
+ bne Linswlp
+ LOADREGS(ea, fp, {r4 - r10, fp, sp, pc})
+Linsw_toosmall:
+ adds r2, r2, #32
+ bmi Linsw_toosmall2
+Linsw2lp: IN(r3)
+ IN(r4)
+ IN(r5)
+ IN(r6)
+ IN(r7)
+ IN(r8)
+ IN(r9)
+ IN(r10)
+ stmia r1!, {r3 - r10}
+ LOADREGS(eqea, fp, {r4 - r10, fp, sp, pc})
+ b Linsw_notaligned
+Linsw_toosmall2:
+ add r2, r2, #32
+Linsw_notaligned:
+ cmp r2, #1
+ LOADREGS(ltea, fp, {r4 - r10, fp, sp, pc})
+ ldr r4, [r0]
+ strb r4, [r1], #1
+ movgt r4, r4, LSR#8
+ strgtb r4, [r1], #1
+ subs r2, r2, #2
+ bgt Linsw_notaligned
+ LOADREGS(ea, fp, {r4 - r10, fp, sp, pc})
+
+@ Purpose: write a block of data from memory to a hardware register.
+@ Proto : outsw(int to_reg, void *from, int len_in_words);
+@ Proto : outswb(int to_reg, void *from, int len_in_bytes);
+@ Notes : increments from
+
+ENTRY(outsw)
+ mov r2, r2, LSL#1
+ENTRY(outswb)
+ mov ip, sp
+ stmfd sp!, {r4 - r8, fp, ip, lr, pc}
+ sub fp, ip, #4
+ addr r3, r0
+ tst r1, #2
+ beq 1f
+ ldr r4, [r1], #2
+ mov r4, r4, lsl #16
+ orr r4, r4, r4, lsr #16
+ str r4, [r3, r0, lsl #2]
+ subs r2, r2, #2
+ LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc})
+1: subs r2, r2, #32
+ blt 2f
+ ldmia r1!, {r4, r5, r6, r7}
+ OUT(r4)
+ OUT(r5)
+ OUT(r6)
+ OUT(r7)
+ ldmia r1!, {r4, r5, r6, r7}
+ OUT(r4)
+ OUT(r5)
+ OUT(r6)
+ OUT(r7)
+ bne 1b
+ LOADREGS(ea, fp, {r4 - r8, fp, sp, pc})
+2: adds r2, r2, #32
+ LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc})
+3: ldr r4, [r1],#2
+ mov r4, r4, lsl#16
+ orr r4, r4, r4, lsr#16
+ str r4, [r3, r0, lsl#2]
+ subs r2, r2, #2
+ bgt 3b
+ LOADREGS(ea, fp, {r4 - r8, fp, sp, pc})
+
+@ Purpose: write a memc register
+@ Proto : void memc_write(int register, int value);
+@ Returns: nothing
+
+#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3)
+ENTRY(memc_write)
+ cmp r0, #7
+ RETINSTR(movgt,pc,lr)
+ mov r0, r0, lsl #17
+ mov r1, r1, lsl #15
+ mov r1, r1, lsr #17
+ orr r0, r0, r1, lsl #2
+ add r0, r0, #0x03600000
+ strb r0, [r0]
+ RETINSTR(mov,pc,lr)
+#define CPSR2SPSR(rt)
+#else
+#define CPSR2SPSR(rt) \
+ mrs rt, cpsr; \
+ msr spsr, rt
+#endif
+
+@ Purpose: call an expansion card loader to read bytes.
+@ Proto : char read_loader(int offset, char *card_base, char *loader);
+@ Returns: byte read
+
+ENTRY(ecard_loader_read)
+ stmfd sp!, {r4 - r12, lr}
+ mov r11, r1
+ mov r1, r0
+ CPSR2SPSR(r0)
+ mov lr, pc
+ mov pc, r2
+ LOADREGS(fd, sp!, {r4 - r12, pc})
+
+@ Purpose: call an expansion card loader to reset the card
+@ Proto : void read_loader(int card_base, char *loader);
+@ Returns: byte read
+
+ENTRY(ecard_loader_reset)
+ stmfd sp!, {r4 - r12, lr}
+ mov r11, r0
+ CPSR2SPSR(r0)
+ mov lr, pc
+ add pc, r1, #8
+ LOADREGS(fd, sp!, {r4 - r12, pc})
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov