swim_asm.S 4.6 KB

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