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