1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * linux/drivers/acorn/scsi/acornscsi-io.S: Acorn SCSI card IO |
4 | */ |
5 | #include <linux/linkage.h> |
6 | |
7 | #include <asm/assembler.h> |
8 | #include <mach/hardware.h> |
9 | |
10 | #if defined(__APCS_32__) |
11 | #define LOADREGS(t,r,l...) ldm##t r, l |
12 | #elif defined(__APCS_26__) |
13 | #define LOADREGS(t,r,l...) ldm##t r, l##^ |
14 | #endif |
15 | |
16 | @ Purpose: transfer a block of data from the acorn scsi card to memory |
17 | @ Proto : void acornscsi_in(unsigned int addr_start, char *buffer, int length) |
18 | @ Returns: nothing |
19 | |
20 | .align |
21 | ENTRY(__acornscsi_in) |
22 | stmfd sp!, {r4 - r7, lr} |
23 | bic r0, r0, #3 |
24 | mov lr, #0xff |
25 | orr lr, lr, #0xff00 |
26 | acornscsi_in16lp: |
27 | subs r2, r2, #16 |
28 | bmi acornscsi_in8 |
29 | ldmia r0!, {r3, r4, r5, r6} |
30 | and r3, r3, lr |
31 | orr r3, r3, r4, lsl #16 |
32 | and r4, r5, lr |
33 | orr r4, r4, r6, lsl #16 |
34 | ldmia r0!, {r5, r6, r7, ip} |
35 | and r5, r5, lr |
36 | orr r5, r5, r6, lsl #16 |
37 | and r6, r7, lr |
38 | orr r6, r6, ip, lsl #16 |
39 | stmia r1!, {r3 - r6} |
40 | bne acornscsi_in16lp |
41 | LOADREGS(fd, sp!, {r4 - r7, pc}) |
42 | |
43 | acornscsi_in8: adds r2, r2, #8 |
44 | bmi acornscsi_in4 |
45 | ldmia r0!, {r3, r4, r5, r6} |
46 | and r3, r3, lr |
47 | orr r3, r3, r4, lsl #16 |
48 | and r4, r5, lr |
49 | orr r4, r4, r6, lsl #16 |
50 | stmia r1!, {r3 - r4} |
51 | LOADREGS(eqfd, sp!, {r4 - r7, pc}) |
52 | sub r2, r2, #8 |
53 | |
54 | acornscsi_in4: adds r2, r2, #4 |
55 | bmi acornscsi_in2 |
56 | ldmia r0!, {r3, r4} |
57 | and r3, r3, lr |
58 | orr r3, r3, r4, lsl #16 |
59 | str r3, [r1], #4 |
60 | LOADREGS(eqfd, sp!, {r4 - r7, pc}) |
61 | sub r2, r2, #4 |
62 | |
63 | acornscsi_in2: adds r2, r2, #2 |
64 | ldr r3, [r0], #4 |
65 | and r3, r3, lr |
66 | strb r3, [r1], #1 |
67 | mov r3, r3, lsr #8 |
68 | strplb r3, [r1], #1 |
69 | LOADREGS(fd, sp!, {r4 - r7, pc}) |
70 | |
71 | @ Purpose: transfer a block of data from memory to the acorn scsi card |
72 | @ Proto : void acornscsi_in(unsigned int addr_start, char *buffer, int length) |
73 | @ Returns: nothing |
74 | |
75 | ENTRY(__acornscsi_out) |
76 | stmfd sp!, {r4 - r6, lr} |
77 | bic r0, r0, #3 |
78 | acornscsi_out16lp: |
79 | subs r2, r2, #16 |
80 | bmi acornscsi_out8 |
81 | ldmia r1!, {r4, r6, ip, lr} |
82 | mov r3, r4, lsl #16 |
83 | orr r3, r3, r3, lsr #16 |
84 | mov r4, r4, lsr #16 |
85 | orr r4, r4, r4, lsl #16 |
86 | mov r5, r6, lsl #16 |
87 | orr r5, r5, r5, lsr #16 |
88 | mov r6, r6, lsr #16 |
89 | orr r6, r6, r6, lsl #16 |
90 | stmia r0!, {r3, r4, r5, r6} |
91 | mov r3, ip, lsl #16 |
92 | orr r3, r3, r3, lsr #16 |
93 | mov r4, ip, lsr #16 |
94 | orr r4, r4, r4, lsl #16 |
95 | mov ip, lr, lsl #16 |
96 | orr ip, ip, ip, lsr #16 |
97 | mov lr, lr, lsr #16 |
98 | orr lr, lr, lr, lsl #16 |
99 | stmia r0!, {r3, r4, ip, lr} |
100 | bne acornscsi_out16lp |
101 | LOADREGS(fd, sp!, {r4 - r6, pc}) |
102 | |
103 | acornscsi_out8: adds r2, r2, #8 |
104 | bmi acornscsi_out4 |
105 | ldmia r1!, {r4, r6} |
106 | mov r3, r4, lsl #16 |
107 | orr r3, r3, r3, lsr #16 |
108 | mov r4, r4, lsr #16 |
109 | orr r4, r4, r4, lsl #16 |
110 | mov r5, r6, lsl #16 |
111 | orr r5, r5, r5, lsr #16 |
112 | mov r6, r6, lsr #16 |
113 | orr r6, r6, r6, lsl #16 |
114 | stmia r0!, {r3, r4, r5, r6} |
115 | LOADREGS(eqfd, sp!, {r4 - r6, pc}) |
116 | |
117 | sub r2, r2, #8 |
118 | acornscsi_out4: adds r2, r2, #4 |
119 | bmi acornscsi_out2 |
120 | ldr r4, [r1], #4 |
121 | mov r3, r4, lsl #16 |
122 | orr r3, r3, r3, lsr #16 |
123 | mov r4, r4, lsr #16 |
124 | orr r4, r4, r4, lsl #16 |
125 | stmia r0!, {r3, r4} |
126 | LOADREGS(eqfd, sp!, {r4 - r6, pc}) |
127 | |
128 | sub r2, r2, #4 |
129 | acornscsi_out2: adds r2, r2, #2 |
130 | ldr r3, [r1], #2 |
131 | strb r3, [r0], #1 |
132 | mov r3, r3, lsr #8 |
133 | strplb r3, [r0], #1 |
134 | LOADREGS(fd, sp!, {r4 - r6, pc}) |
135 | |
136 | |