patch-2.1.101 linux/drivers/acorn/block/mfm.S
Next file: linux/drivers/acorn/char/Config.in
Previous file: linux/drivers/acorn/block/ide-rapide.c
Back to the patch index
Back to the overall index
- Lines: 164
- Date:
Fri May 8 00:42:38 1998
- Orig file:
v2.1.100/linux/drivers/acorn/block/mfm.S
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/block/mfm.S linux/drivers/acorn/block/mfm.S
@@ -0,0 +1,163 @@
+@ Read/Write DMA code for the ST506/MFM hard drive controllers on the A400
+@ motherboard on ST506 podules.
+@ (c) David Alan Gilbert (gilbertd@cs.man.ac.uk) 1996
+
+#include <asm/assembler.h>
+
+_hdc63463_irqdata:
+@ Controller base address
+ .global _hdc63463_baseaddress
+_hdc63463_baseaddress:
+ .word 0
+
+ .global _hdc63463_irqpolladdress
+_hdc63463_irqpolladdress:
+ .word 0
+
+ .global _hdc63463_irqpollmask
+_hdc63463_irqpollmask:
+ .word 0
+
+@ where to read/write data from the kernel data space
+ .global _hdc63463_dataptr
+_hdc63463_dataptr:
+ .word 0
+
+@ Number of bytes left to transfer
+ .global _hdc63463_dataleft
+_hdc63463_dataleft:
+ .word 0
+
+@ -------------------------------------------------------------------------
+@ hdc63463_writedma: DMA from host to controller
+@ internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask
+@ r3=data ptr, r4=data left, r5,r6=temporary
+ .global _hdc63463_writedma
+_hdc63463_writedma:
+ stmfd sp!,{r4-r7}
+ adr r5,_hdc63463_irqdata
+ ldmia r5,{r0,r1,r2,r3,r4}
+
+
+writedma_again:
+
+ @ test number of remaining bytes to transfer
+ cmp r4,#0
+ beq writedma_end
+ bmi writedma_end
+
+ @ Check the hdc is interrupting
+ ldrb r5,[r1,#0]
+ tst r5,r2
+ beq writedma_end
+
+ @ Transfer a block of upto 256 bytes
+ cmp r4,#256
+ movlt r7,r4
+ movge r7,#256
+
+ @ Check the hdc is still busy and command has not ended and no errors
+ ldr r5,[r0,#32] @ Status reg - 16 bit - its the top few bits which are status
+ @ think we should continue DMA until it drops busy - perhaps this was
+ @ the main problem with corrected errors causing a hang
+ @tst r5,#0x3c00 @ Test for things which should be off
+ @bne writedma_end
+ and r5,r5,#0x8000 @ This is test for things which should be on: Busy
+ cmp r5,#0x8000
+ bne writedma_end
+
+ @ Bytes remaining at end
+ sub r4,r4,r7
+
+ @ HDC Write register location
+ add r0,r0,#32+8
+
+writedma_loop:
+ @ OK - pretty sure we should be doing this
+
+ ldr r5,[r3],#4 @ Get a word to be written
+ @ get bottom half to be sent first
+ mov r6,r5,lsl#16 @ Separate the first 2 bytes
+ orr r2,r6,r6,lsr #16 @ Duplicate them in the bottom half of the word
+ @ now the top half
+ mov r6,r5,lsr#16 @ Get 2nd 2 bytes
+ orr r6,r6,r6,lsl#16 @ Duplicate
+ @str r6,[r0] @ to hdc
+ stmia r0,{r2,r6}
+ subs r7,r7,#4 @ Dec. number of bytes left
+ bne writedma_loop
+
+ @ If we were too slow we had better go through again - DAG - took out with new interrupt routine
+ @ sub r0,r0,#32+8
+ @ adr r2,_hdc63463_irqdata
+ @ ldr r2,[r2,#8]
+ @ b writedma_again
+
+writedma_end:
+ adr r5,_hdc63463_irqdata+12
+ stmia r5,{r3,r4}
+ ldmfd sp!,{r4-r7}
+ RETINSTR(mov,pc,lr)
+
+@ -------------------------------------------------------------------------
+@ hdc63463_readdma: DMA from controller to host
+@ internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask
+@ r3=data ptr, r4=data left, r5,r6=temporary
+ .global _hdc63463_readdma
+_hdc63463_readdma:
+ stmfd sp!,{r4-r7}
+ adr r5,_hdc63463_irqdata
+ ldmia r5,{r0,r1,r2,r3,r4}
+
+readdma_again:
+ @ test number of remaining bytes to transfer
+ cmp r4,#0
+ beq readdma_end
+ bmi readdma_end
+
+ @ Check the hdc is interrupting
+ ldrb r5,[r1,#0]
+ tst r5,r2
+ beq readdma_end
+
+ @ Check the hdc is still busy and command has not ended and no errors
+ ldr r5,[r0,#32] @ Status reg - 16 bit - its the top few bits which are status
+ @ think we should continue DMA until it drops busy - perhaps this was
+ @ the main problem with corrected errors causing a hang
+ @tst r5,#0x3c00 @ Test for things which should be off
+ @bne readdma_end
+ and r5,r5,#0x8000 @ This is test for things which should be on: Busy
+ cmp r5,#0x8000
+ bne readdma_end
+
+ @ Transfer a block of upto 256 bytes
+ cmp r4,#256
+ movlt r7,r4
+ movge r7,#256
+
+ @ Bytes remaining at end
+ sub r4,r4,r7
+
+ @ Set a pointer to the data register in the HDC
+ add r0,r0,#8
+readdma_loop:
+ @ OK - pretty sure we should be doing this
+ ldmia r0,{r5,r6}
+ mov r5,r5,lsl#16
+ mov r6,r6,lsl#16
+ orr r6,r6,r5,lsr #16
+ str r6,[r3],#4
+ subs r7,r7,#4 @ Decrement bytes to go
+ bne readdma_loop
+
+ @ Try reading multiple blocks - if this was fast enough then I dont think
+ @ this should help - NO taken out DAG - new interrupt handler has
+ @ non-consecutive memory blocks
+ @ sub r0,r0,#8
+ @ b readdma_again
+
+readdma_end:
+ adr r5,_hdc63463_irqdata+12
+ stmia r5,{r3,r4}
+ ldmfd sp!,{r4-r7}
+ RETINSTR(mov,pc,lr)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov