swim_asm.S 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * low-level functions for the SWIM floppy controller
  4. *
  5. * needs assembly language because is very timing dependent
  6. * this controller exists only on macintosh 680x0 based
  7. *
  8. * Copyright (C) 2004,2008 Laurent Vivier <[email protected]>
  9. *
  10. * based on Alastair Bridgewater SWIM analysis, 2001
  11. * based on netBSD IWM driver (c) 1997, 1998 Hauke Fath.
  12. *
  13. * 2004-08-21 (lv) - Initial implementation
  14. * 2008-11-05 (lv) - add get_swim_mode
  15. */
  16. .equ write_data, 0x0000
  17. .equ write_mark, 0x0200
  18. .equ write_CRC, 0x0400
  19. .equ write_parameter,0x0600
  20. .equ write_phase, 0x0800
  21. .equ write_setup, 0x0a00
  22. .equ write_mode0, 0x0c00
  23. .equ write_mode1, 0x0e00
  24. .equ read_data, 0x1000
  25. .equ read_mark, 0x1200
  26. .equ read_error, 0x1400
  27. .equ read_parameter, 0x1600
  28. .equ read_phase, 0x1800
  29. .equ read_setup, 0x1a00
  30. .equ read_status, 0x1c00
  31. .equ read_handshake, 0x1e00
  32. .equ o_side, 0
  33. .equ o_track, 1
  34. .equ o_sector, 2
  35. .equ o_size, 3
  36. .equ o_crc0, 4
  37. .equ o_crc1, 5
  38. .equ seek_time, 30000
  39. .equ max_retry, 40
  40. .equ sector_size, 512
  41. .global swim_read_sector_header
  42. swim_read_sector_header:
  43. link %a6, #0
  44. moveml %d1-%d5/%a0-%a4,%sp@-
  45. movel %a6@(0x0c), %a4
  46. bsr mfm_read_addrmark
  47. moveml %sp@+, %d1-%d5/%a0-%a4
  48. unlk %a6
  49. rts
  50. sector_address_mark:
  51. .byte 0xa1, 0xa1, 0xa1, 0xfe
  52. sector_data_mark:
  53. .byte 0xa1, 0xa1, 0xa1, 0xfb
  54. mfm_read_addrmark:
  55. movel %a6@(0x08), %a3
  56. lea %a3@(read_handshake), %a2
  57. lea %a3@(read_mark), %a3
  58. moveq #-1, %d0
  59. movew #seek_time, %d2
  60. wait_header_init:
  61. tstb %a3@(read_error - read_mark)
  62. moveb #0x18, %a3@(write_mode0 - read_mark)
  63. moveb #0x01, %a3@(write_mode1 - read_mark)
  64. moveb #0x01, %a3@(write_mode0 - read_mark)
  65. tstb %a3@(read_error - read_mark)
  66. moveb #0x08, %a3@(write_mode1 - read_mark)
  67. lea sector_address_mark, %a0
  68. moveq #3, %d1
  69. wait_addr_mark_byte:
  70. tstb %a2@
  71. dbmi %d2, wait_addr_mark_byte
  72. bpl header_exit
  73. moveb %a3@, %d3
  74. cmpb %a0@+, %d3
  75. dbne %d1, wait_addr_mark_byte
  76. bne wait_header_init
  77. moveq #max_retry, %d2
  78. amark0: tstb %a2@
  79. dbmi %d2, amark0
  80. bpl signal_nonyb
  81. moveb %a3@, %a4@(o_track)
  82. moveq #max_retry, %d2
  83. amark1: tstb %a2@
  84. dbmi %d2, amark1
  85. bpl signal_nonyb
  86. moveb %a3@, %a4@(o_side)
  87. moveq #max_retry, %d2
  88. amark2: tstb %a2@
  89. dbmi %d2, amark2
  90. bpl signal_nonyb
  91. moveb %a3@, %a4@(o_sector)
  92. moveq #max_retry, %d2
  93. amark3: tstb %a2@
  94. dbmi %d2, amark3
  95. bpl signal_nonyb
  96. moveb %a3@, %a4@(o_size)
  97. moveq #max_retry, %d2
  98. crc0: tstb %a2@
  99. dbmi %d2, crc0
  100. bpl signal_nonyb
  101. moveb %a3@, %a4@(o_crc0)
  102. moveq #max_retry, %d2
  103. crc1: tstb %a2@
  104. dbmi %d2, crc1
  105. bpl signal_nonyb
  106. moveb %a3@, %a4@(o_crc1)
  107. tstb %a3@(read_error - read_mark)
  108. header_exit:
  109. moveq #0, %d0
  110. moveb #0x18, %a3@(write_mode0 - read_mark)
  111. rts
  112. signal_nonyb:
  113. moveq #-1, %d0
  114. moveb #0x18, %a3@(write_mode0 - read_mark)
  115. rts
  116. .global swim_read_sector_data
  117. swim_read_sector_data:
  118. link %a6, #0
  119. moveml %d1-%d5/%a0-%a5,%sp@-
  120. movel %a6@(0x0c), %a4
  121. bsr mfm_read_data
  122. moveml %sp@+, %d1-%d5/%a0-%a5
  123. unlk %a6
  124. rts
  125. mfm_read_data:
  126. movel %a6@(0x08), %a3
  127. lea %a3@(read_handshake), %a2
  128. lea %a3@(read_data), %a5
  129. lea %a3@(read_mark), %a3
  130. movew #seek_time, %d2
  131. wait_data_init:
  132. tstb %a3@(read_error - read_mark)
  133. moveb #0x18, %a3@(write_mode0 - read_mark)
  134. moveb #0x01, %a3@(write_mode1 - read_mark)
  135. moveb #0x01, %a3@(write_mode0 - read_mark)
  136. tstb %a3@(read_error - read_mark)
  137. moveb #0x08, %a3@(write_mode1 - read_mark)
  138. lea sector_data_mark, %a0
  139. moveq #3, %d1
  140. /* wait data address mark */
  141. wait_data_mark_byte:
  142. tstb %a2@
  143. dbmi %d2, wait_data_mark_byte
  144. bpl data_exit
  145. moveb %a3@, %d3
  146. cmpb %a0@+, %d3
  147. dbne %d1, wait_data_mark_byte
  148. bne wait_data_init
  149. /* read data */
  150. tstb %a3@(read_error - read_mark)
  151. movel #sector_size-1, %d4 /* sector size */
  152. read_new_data:
  153. movew #max_retry, %d2
  154. read_data_loop:
  155. moveb %a2@, %d5
  156. andb #0xc0, %d5
  157. dbne %d2, read_data_loop
  158. beq data_exit
  159. moveb %a5@, %a4@+
  160. andb #0x40, %d5
  161. dbne %d4, read_new_data
  162. beq exit_loop
  163. moveb %a5@, %a4@+
  164. dbra %d4, read_new_data
  165. exit_loop:
  166. /* read CRC */
  167. movew #max_retry, %d2
  168. data_crc0:
  169. tstb %a2@
  170. dbmi %d2, data_crc0
  171. bpl data_exit
  172. moveb %a3@, %d5
  173. moveq #max_retry, %d2
  174. data_crc1:
  175. tstb %a2@
  176. dbmi %d2, data_crc1
  177. bpl data_exit
  178. moveb %a3@, %d5
  179. tstb %a3@(read_error - read_mark)
  180. moveb #0x18, %a3@(write_mode0 - read_mark)
  181. /* return number of bytes read */
  182. movel #sector_size, %d0
  183. addw #1, %d4
  184. subl %d4, %d0
  185. rts
  186. data_exit:
  187. moveb #0x18, %a3@(write_mode0 - read_mark)
  188. moveq #-1, %d0
  189. rts