PageRenderTime 29ms CodeModel.GetById 18ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/acorn/block/mfm.S

https://bitbucket.org/evzijst/gittest
Assembly | 162 lines | 135 code | 27 blank | 0 comment | 6 complexity | f3068bbb1fa0631103fa91d8ce875a0b MD5 | raw file
  1@ Read/Write DMA code for the ST506/MFM hard drive controllers on the A400 Acorn Archimedes
  2@   motherboard and on ST506 expansion podules.
  3@ (c) David Alan Gilbert (linux@treblig.org) 1996-1999
  4
  5#include <asm/assembler.h>
  6 
  7hdc63463_irqdata:
  8@ Controller base address
  9  .global hdc63463_baseaddress
 10hdc63463_baseaddress:
 11  .word 0
 12
 13  .global hdc63463_irqpolladdress
 14hdc63463_irqpolladdress:
 15  .word 0
 16 
 17  .global hdc63463_irqpollmask
 18hdc63463_irqpollmask:
 19  .word 0
 20
 21@ where to read/write data  from the kernel data space
 22  .global hdc63463_dataptr
 23hdc63463_dataptr:
 24  .word 0
 25
 26@ Number of bytes left to transfer
 27  .global hdc63463_dataleft
 28hdc63463_dataleft:
 29  .word 0
 30
 31@ -------------------------------------------------------------------------
 32@ hdc63463_writedma: DMA from host to controller
 33@  internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask
 34@                      r3=data ptr, r4=data left, r5,r6=temporary
 35  .global hdc63463_writedma
 36hdc63463_writedma:
 37  stmfd sp!,{r4-r7}
 38  adr r5,hdc63463_irqdata
 39  ldmia r5,{r0,r1,r2,r3,r4}
 40
 41writedma_again:
 42
 43  @ test number of remaining bytes to transfer
 44  cmp r4,#0
 45  beq writedma_end
 46  bmi writedma_end
 47
 48  @ Check the hdc is interrupting
 49  ldrb r5,[r1,#0]
 50  tst r5,r2
 51  beq writedma_end
 52
 53  @ Transfer a block of upto 256 bytes
 54  cmp r4,#256
 55  movlt r7,r4
 56  movge r7,#256
 57
 58  @ Check the hdc is still busy and command has not ended and no errors
 59  ldr r5,[r0,#32]     @ Status reg - 16 bit - its the top few bits which are status
 60  @ think we should continue DMA until it drops busy - perhaps this was
 61  @ the main problem with corrected errors causing a hang
 62  @tst r5,#0x3c00        @ Test for things which should be off
 63  @bne writedma_end
 64  and r5,r5,#0x8000        @ This is test for things which should be on: Busy
 65  cmp r5,#0x8000
 66  bne writedma_end 
 67
 68  @ Bytes remaining at end
 69  sub r4,r4,r7
 70
 71  @ HDC Write register location
 72  add r0,r0,#32+8
 73
 74writedma_loop:
 75  @ OK - pretty sure we should be doing this
 76
 77  ldr r5,[r3],#4          @ Get a word to be written
 78  @ get bottom half to be sent first
 79  mov r6,r5,lsl#16        @ Separate the first 2 bytes
 80  orr r2,r6,r6,lsr #16    @ Duplicate them in the bottom half of the word
 81  @ now the top half
 82  mov r6,r5,lsr#16        @ Get 2nd 2 bytes
 83  orr r6,r6,r6,lsl#16     @ Duplicate
 84  @str r6,[r0]       @ to hdc
 85  stmia r0,{r2,r6}
 86  subs r7,r7,#4           @ Dec. number of bytes left
 87  bne writedma_loop
 88
 89  @ If we were too slow we had better go through again - DAG - took out with new interrupt routine
 90  @ sub r0,r0,#32+8
 91  @ adr r2,hdc63463_irqdata
 92  @ ldr r2,[r2,#8]
 93  @ b writedma_again
 94
 95writedma_end:
 96  adr r5,hdc63463_irqdata+12
 97  stmia r5,{r3,r4}
 98  ldmfd sp!,{r4-r7}
 99  RETINSTR(mov,pc,lr)
100
101@ -------------------------------------------------------------------------
102@ hdc63463_readdma: DMA from controller to host
103@  internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask
104@                      r3=data ptr, r4=data left, r5,r6=temporary
105  .global hdc63463_readdma
106hdc63463_readdma:
107  stmfd sp!,{r4-r7}
108  adr r5,hdc63463_irqdata
109  ldmia r5,{r0,r1,r2,r3,r4}
110
111readdma_again:
112  @ test number of remaining bytes to transfer
113  cmp r4,#0
114  beq readdma_end
115  bmi readdma_end
116
117  @ Check the hdc is interrupting
118  ldrb r5,[r1,#0]
119  tst r5,r2
120  beq readdma_end
121
122  @ Check the hdc is still busy and command has not ended and no errors
123  ldr r5,[r0,#32]     @ Status reg - 16 bit - its the top few bits which are status
124  @ think we should continue DMA until it drops busy - perhaps this was
125  @ the main problem with corrected errors causing a hang
126  @tst r5,#0x3c00      @ Test for things which should be off
127  @bne readdma_end
128  and r5,r5,#0x8000        @ This is test for things which should be on: Busy
129  cmp r5,#0x8000
130  bne readdma_end 
131
132  @ Transfer a block of upto 256 bytes
133  cmp r4,#256
134  movlt r7,r4
135  movge r7,#256
136
137  @ Bytes remaining at end
138  sub r4,r4,r7
139
140  @ Set a pointer to the data register in the HDC
141  add r0,r0,#8
142readdma_loop:
143  @ OK - pretty sure we should be doing this
144  ldmia r0,{r5,r6}
145  mov r5,r5,lsl#16
146  mov r6,r6,lsl#16
147  orr r6,r6,r5,lsr #16
148  str r6,[r3],#4
149  subs r7,r7,#4        @ Decrement bytes to go
150  bne readdma_loop
151
152  @ Try reading multiple blocks - if this was fast enough then I do not think
153  @ this should help - NO taken out DAG - new interrupt handler has
154  @ non-consecutive memory blocks
155  @ sub r0,r0,#8
156  @ b readdma_again
157
158readdma_end:
159  adr r5,hdc63463_irqdata+12
160  stmia r5,{r3,r4}
161  ldmfd sp!,{r4-r7}
162  RETINSTR(mov,pc,lr)