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