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 <asm/hardware.h>
12
13#if (IO_BASE == (PCIO_BASE & 0xff000000))
14#define ADDR(off,reg)						\
15		tst	off, $0x80000000			;\
16		mov	reg, $IO_BASE				;\
17		orreq	reg, reg, $(PCIO_BASE & 0x00ff0000)
18#else
19#define ADDR(off,reg)						\
20		tst	off, $0x80000000			;\
21		movne	reg, $IO_BASE				;\
22		moveq	reg, $(PCIO_BASE & 0xff000000)		;\
23		orreq	reg, reg, $(PCIO_BASE & 0x00ff0000)
24#endif
25
26@ Purpose: transfer a block of data from the acorn scsi card to memory
27@ Proto  : void acornscsi_in(unsigned int addr_start, char *buffer, int length)
28@ Returns: nothing
29
30		.align
31ENTRY(__acornscsi_in)
32		stmfd	sp!, {r4 - r7, lr}
33		bic	r0, r0, #3
34		mov	lr, #0xff
35		orr	lr, lr, #0xff00
36acornscsi_in16lp:
37		subs	r2, r2, #16
38		bmi	acornscsi_in8
39		ldmia	r0!, {r3, r4, r5, r6}
40		and	r3, r3, lr
41		orr	r3, r3, r4, lsl #16
42		and 	r4, r5, lr
43		orr	r4, r4, r6, lsl #16
44		ldmia	r0!, {r5, r6, r7, ip}
45		and	r5, r5, lr
46		orr	r5, r5, r6, lsl #16
47		and	r6, r7, lr
48		orr	r6, r6, ip, lsl #16
49		stmia	r1!, {r3 - r6}
50		bne	acornscsi_in16lp
51		LOADREGS(fd, sp!, {r4 - r7, pc})
52
53acornscsi_in8:	adds	r2, r2, #8
54		bmi	acornscsi_in4
55		ldmia	r0!, {r3, r4, r5, r6}
56		and	r3, r3, lr
57		orr	r3, r3, r4, lsl #16
58		and	r4, r5, lr
59		orr	r4, r4, r6, lsl #16
60		stmia	r1!, {r3 - r4}
61		LOADREGS(eqfd, sp!, {r4 - r7, pc})
62		sub	r2, r2, #8
63
64acornscsi_in4:	adds	r2, r2, #4
65		bmi	acornscsi_in2
66		ldmia	r0!, {r3, r4}
67		and	r3, r3, lr
68		orr	r3, r3, r4, lsl #16
69		str	r3, [r1], #4
70		LOADREGS(eqfd, sp!, {r4 - r7, pc})
71		sub	r2, r2, #4
72
73acornscsi_in2:	adds	r2, r2, #2
74		ldr	r3, [r0], #4
75		and	r3, r3, lr
76		strb	r3, [r1], #1
77		mov	r3, r3, lsr #8
78		strplb	r3, [r1], #1
79		LOADREGS(fd, sp!, {r4 - r7, pc})
80
81@ Purpose: transfer a block of data from memory to the acorn scsi card
82@ Proto  : void acornscsi_in(unsigned int addr_start, char *buffer, int length)
83@ Returns: nothing
84
85ENTRY(__acornscsi_out)
86		stmfd	sp!, {r4 - r6, lr}
87		bic	r0, r0, #3
88acornscsi_out16lp:
89		subs	r2, r2, #16
90		bmi	acornscsi_out8
91		ldmia	r1!, {r4, r6, ip, lr}
92		mov	r3, r4, lsl #16
93		orr	r3, r3, r3, lsr #16
94		mov	r4, r4, lsr #16
95		orr	r4, r4, r4, lsl #16
96		mov	r5, r6, lsl #16
97		orr	r5, r5, r5, lsr #16
98		mov	r6, r6, lsr #16
99		orr	r6, r6, r6, lsl #16
100		stmia	r0!, {r3, r4, r5, r6}
101		mov	r3, ip, lsl #16
102		orr	r3, r3, r3, lsr #16
103		mov	r4, ip, lsr #16
104		orr	r4, r4, r4, lsl #16
105		mov	ip, lr, lsl #16
106		orr	ip, ip, ip, lsr #16
107		mov	lr, lr, lsr #16
108		orr	lr, lr, lr, lsl #16
109		stmia	r0!, {r3, r4, ip, lr}
110		bne	acornscsi_out16lp
111		LOADREGS(fd, sp!, {r4 - r6, pc})
112
113acornscsi_out8:	adds	r2, r2, #8
114		bmi	acornscsi_out4
115		ldmia	r1!, {r4, r6}
116		mov	r3, r4, lsl #16
117		orr	r3, r3, r3, lsr #16
118		mov	r4, r4, lsr #16
119		orr	r4, r4, r4, lsl #16
120		mov	r5, r6, lsl #16
121		orr	r5, r5, r5, lsr #16
122		mov	r6, r6, lsr #16
123		orr	r6, r6, r6, lsl #16
124		stmia	r0!, {r3, r4, r5, r6}
125		LOADREGS(eqfd, sp!, {r4 - r6, pc})
126
127		sub	r2, r2, #8
128acornscsi_out4:	adds	r2, r2, #4
129		bmi	acornscsi_out2
130		ldr	r4, [r1], #4
131		mov	r3, r4, lsl #16
132		orr	r3, r3, r3, lsr #16
133		mov	r4, r4, lsr #16
134		orr	r4, r4, r4, lsl #16
135		stmia	r0!, {r3, r4}
136		LOADREGS(eqfd, sp!, {r4 - r6, pc})
137
138		sub	r2, r2, #4
139acornscsi_out2:	adds	r2, r2, #2
140		ldr	r3, [r1], #2
141		strb	r3, [r0], #1
142		mov	r3, r3, lsr #8
143		strplb	r3, [r0], #1
144		LOADREGS(fd, sp!, {r4 - r6, pc})
145