| /* SPDX-License-Identifier: GPL-2.0-only */ | 
 | /* | 
 |  *  linux/drivers/acorn/scsi/acornscsi-io.S: Acorn SCSI card IO | 
 |  */ | 
 | #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}) | 
 |  |