summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/arm/acornscsi-io.S
blob: 22171b2110a852cfd2fadc611e3220f39dbb349b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 *  linux/drivers/acorn/scsi/acornscsi-io.S: Acorn SCSI card IO
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/linkage.h>

#include <asm/assembler.h>
#include <mach/hardware.h>

#if defined(__APCS_32__)
#define LOADREGS(t,r,l...)	ldm##t	r, l
#elif defined(__APCS_26__)
#define LOADREGS(t,r,l...)	ldm##t	r, l##^
#endif

@ Purpose: transfer a block of data from the acorn scsi card to memory
@ Proto  : void acornscsi_in(unsigned int addr_start, char *buffer, int length)
@ Returns: nothing

		.align
ENTRY(__acornscsi_in)
		stmfd	sp!, {r4 - r7, lr}
		bic	r0, r0, #3
		mov	lr, #0xff
		orr	lr, lr, #0xff00
acornscsi_in16lp:
		subs	r2, r2, #16
		bmi	acornscsi_in8
		ldmia	r0!, {r3, r4, r5, r6}
		and	r3, r3, lr
		orr	r3, r3, r4, lsl #16
		and 	r4, r5, lr
		orr	r4, r4, r6, lsl #16
		ldmia	r0!, {r5, r6, r7, ip}
		and	r5, r5, lr
		orr	r5, r5, r6, lsl #16
		and	r6, r7, lr
		orr	r6, r6, ip, lsl #16
		stmia	r1!, {r3 - r6}
		bne	acornscsi_in16lp
		LOADREGS(fd, sp!, {r4 - r7, pc})

acornscsi_in8:	adds	r2, r2, #8
		bmi	acornscsi_in4
		ldmia	r0!, {r3, r4, r5, r6}
		and	r3, r3, lr
		orr	r3, r3, r4, lsl #16
		and	r4, r5, lr
		orr	r4, r4, r6, lsl #16
		stmia	r1!, {r3 - r4}
		LOADREGS(eqfd, sp!, {r4 - r7, pc})
		sub	r2, r2, #8

acornscsi_in4:	adds	r2, r2, #4
		bmi	acornscsi_in2
		ldmia	r0!, {r3, r4}
		and	r3, r3, lr
		orr	r3, r3, r4, lsl #16
		str	r3, [r1], #4
		LOADREGS(eqfd, sp!, {r4 - r7, pc})
		sub	r2, r2, #4

acornscsi_in2:	adds	r2, r2, #2
		ldr	r3, [r0], #4
		and	r3, r3, lr
		strb	r3, [r1], #1
		mov	r3, r3, lsr #8
		strplb	r3, [r1], #1
		LOADREGS(fd, sp!, {r4 - r7, pc})

@ Purpose: transfer a block of data from memory to the acorn scsi card
@ Proto  : void acornscsi_in(unsigned int addr_start, char *buffer, int length)
@ Returns: nothing

ENTRY(__acornscsi_out)
		stmfd	sp!, {r4 - r6, lr}
		bic	r0, r0, #3
acornscsi_out16lp:
		subs	r2, r2, #16
		bmi	acornscsi_out8
		ldmia	r1!, {r4, r6, ip, lr}
		mov	r3, r4, lsl #16
		orr	r3, r3, r3, lsr #16
		mov	r4, r4, lsr #16
		orr	r4, r4, r4, lsl #16
		mov	r5, r6, lsl #16
		orr	r5, r5, r5, lsr #16
		mov	r6, r6, lsr #16
		orr	r6, r6, r6, lsl #16
		stmia	r0!, {r3, r4, r5, r6}
		mov	r3, ip, lsl #16
		orr	r3, r3, r3, lsr #16
		mov	r4, ip, lsr #16
		orr	r4, r4, r4, lsl #16
		mov	ip, lr, lsl #16
		orr	ip, ip, ip, lsr #16
		mov	lr, lr, lsr #16
		orr	lr, lr, lr, lsl #16
		stmia	r0!, {r3, r4, ip, lr}
		bne	acornscsi_out16lp
		LOADREGS(fd, sp!, {r4 - r6, pc})

acornscsi_out8:	adds	r2, r2, #8
		bmi	acornscsi_out4
		ldmia	r1!, {r4, r6}
		mov	r3, r4, lsl #16
		orr	r3, r3, r3, lsr #16
		mov	r4, r4, lsr #16
		orr	r4, r4, r4, lsl #16
		mov	r5, r6, lsl #16
		orr	r5, r5, r5, lsr #16
		mov	r6, r6, lsr #16
		orr	r6, r6, r6, lsl #16
		stmia	r0!, {r3, r4, r5, r6}
		LOADREGS(eqfd, sp!, {r4 - r6, pc})

		sub	r2, r2, #8
acornscsi_out4:	adds	r2, r2, #4
		bmi	acornscsi_out2
		ldr	r4, [r1], #4
		mov	r3, r4, lsl #16
		orr	r3, r3, r3, lsr #16
		mov	r4, r4, lsr #16
		orr	r4, r4, r4, lsl #16
		stmia	r0!, {r3, r4}
		LOADREGS(eqfd, sp!, {r4 - r6, pc})

		sub	r2, r2, #4
acornscsi_out2:	adds	r2, r2, #2
		ldr	r3, [r1], #2
		strb	r3, [r0], #1
		mov	r3, r3, lsr #8
		strplb	r3, [r0], #1
		LOADREGS(fd, sp!, {r4 - r6, pc})