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 <Laurent@lvivier.info> 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 17 .equ .Lwrite_data, 0x0000 18 .equ .Lwrite_mark, 0x0200 19 .equ .Lwrite_CRC, 0x0400 20 .equ .Lwrite_parameter, 0x0600 21 .equ .Lwrite_phase, 0x0800 22 .equ .Lwrite_setup, 0x0a00 23 .equ .Lwrite_mode0, 0x0c00 24 .equ .Lwrite_mode1, 0x0e00 25 .equ .Lread_data, 0x1000 26 .equ .Lread_mark, 0x1200 27 .equ .Lread_error, 0x1400 28 .equ .Lread_parameter, 0x1600 29 .equ .Lread_phase, 0x1800 30 .equ .Lread_setup, 0x1a00 31 .equ .Lread_status, 0x1c00 32 .equ .Lread_handshake, 0x1e00 33 34 .equ .Lo_side, 0 35 .equ .Lo_track, 1 36 .equ .Lo_sector, 2 37 .equ .Lo_size, 3 38 .equ .Lo_crc0, 4 39 .equ .Lo_crc1, 5 40 41 .equ .Lseek_time, 30000 42 .equ .Lmax_retry, 40 43 .equ .Lsector_size, 512 44 .equ .Lmark_sequence_len, 4 45 46 .equ .Lmr_clear_fifo, 0x01 47 .equ .Lmr_action, 0x08 48 .equ .Lmr_write_action, 0x18 49 50 .equ .Lhr_crc_error, 0x02 51 .equ .Lhr_fifo_2bytes, 0x40 52 .equ .Lhr_fifo_1byte, 0x80 53 54.Lmfm_mark_check: 55 /* 56 * This subroutine reads and validates a mark byte sequence. 57 * On entry, %a1 and %d4 shall hold the location and length (resp.) 58 * of the mark byte array. 59 * %a2 and %a3 shall hold the locations of the handshake and mark 60 * registers. 61 * Returns zero in %d1 for success. 62 */ 63 64 moveq #-1, %d1 65 subq #1, %d4 66 movew #.Lseek_time, %d2 67 685: tstb %a2@ 69 dbmi %d2, 5b 70 bpl 6f 71 72 moveb %a3@, %d3 73 cmpb %a1@+, %d3 74 dbne %d4, 5b 75 bne 6f 76 77 moveq #0, %d1 786: rts 79 80 .global swim_read_sector_header 81swim_read_sector_header: 82 link %a6, #0 83 moveml %d1-%d5/%a0-%a5,%sp@- 84 movel %a6@(0x0c), %a4 85 moveq #-1, %d0 86 bsr .Lmfm_read_header 87 moveml %sp@+, %d1-%d5/%a0-%a5 88 unlk %a6 89 rts 90 91.Lsector_address_mark: 92 .byte 0xa1, 0xa1, 0xa1, 0xfe 93.Lsector_data_mark: 94 .byte 0xa1, 0xa1, 0xa1, 0xfb 95 96.Lmfm_read_header: 97 movel %a6@(0x08), %a3 98 lea %a3@(.Lread_handshake), %a2 99 lea %a3@(.Lread_data), %a5 100 lea %a3@(.Lread_mark), %a3 101 102 moveb #.Lmr_write_action, %a3@(.Lwrite_mode0 - .Lread_mark) 103 moveb #.Lmr_clear_fifo, %a3@(.Lwrite_mode1 - .Lread_mark) 104 moveb #.Lmr_clear_fifo, %a3@(.Lwrite_mode0 - .Lread_mark) 105 tstb %a3@(.Lread_error - .Lread_mark) 106 moveb #.Lmr_action, %a3@(.Lwrite_mode1 - .Lread_mark) 107 108 lea .Lsector_address_mark, %a1 109 moveq #.Lmark_sequence_len, %d4 110 bsr .Lmfm_mark_check 111 tstl %d1 112 bne .Lsignal_nonyb 113 114 /* read header */ 115 116 moveq #.Lmax_retry, %d2 117.Lamark0: 118 tstb %a2@ 119 dbmi %d2, .Lamark0 120 bpl .Lsignal_nonyb 121 122 moveb %a5@, %a4@(.Lo_track) 123 124 moveq #.Lmax_retry, %d2 125.Lamark1: 126 tstb %a2@ 127 dbmi %d2, .Lamark1 128 bpl .Lsignal_nonyb 129 130 moveb %a5@, %a4@(.Lo_side) 131 132 moveq #.Lmax_retry, %d2 133.Lamark2: 134 tstb %a2@ 135 dbmi %d2, .Lamark2 136 bpl .Lsignal_nonyb 137 138 moveb %a5@, %a4@(.Lo_sector) 139 140 moveq #.Lmax_retry, %d2 141.Lamark3: 142 tstb %a2@ 143 dbmi %d2, .Lamark3 144 bpl .Lsignal_nonyb 145 146 moveb %a5@, %a4@(.Lo_size) 147 148 moveq #.Lmax_retry, %d2 149.Lcrc0: 150 tstb %a2@ 151 dbmi %d2, .Lcrc0 152 bpl .Lsignal_nonyb 153 154 moveb %a5@, %a4@(.Lo_crc0) 155 156 moveq #.Lmax_retry, %d2 157.Lcrc1: 158 tstb %a2@ 159 dbmi %d2, .Lcrc1 160 bpl .Lsignal_nonyb 161 162 moveb %a5@, %a4@(.Lo_crc1) 163 164 moveb %a2@, %d5 165 andb #.Lhr_crc_error, %d5 166 bne .Lsignal_nonyb 167 168 moveq #0, %d0 169.Lsignal_nonyb: 170 moveb #.Lmr_write_action, %a3@(.Lwrite_mode0 - .Lread_mark) 171 rts 172 173 .global swim_read_sector_data 174swim_read_sector_data: 175 link %a6, #0 176 moveml %d1-%d5/%a0-%a5,%sp@- 177 movel %a6@(0x0c), %a4 178 moveq #-1, %d0 179 bsr .Lmfm_read_data 180 moveml %sp@+, %d1-%d5/%a0-%a5 181 unlk %a6 182 rts 183 184.Lmfm_read_data: 185 movel %a6@(0x08), %a3 186 lea %a3@(.Lread_handshake), %a2 187 lea %a3@(.Lread_data), %a5 188 lea %a3@(.Lread_mark), %a3 189 190 moveb #.Lmr_write_action, %a3@(.Lwrite_mode0 - .Lread_mark) 191 moveb #.Lmr_clear_fifo, %a3@(.Lwrite_mode1 - .Lread_mark) 192 moveb #.Lmr_clear_fifo, %a3@(.Lwrite_mode0 - .Lread_mark) 193 tstb %a3@(.Lread_error - .Lread_mark) 194 moveb #.Lmr_action, %a3@(.Lwrite_mode1 - .Lread_mark) 195 196 lea .Lsector_data_mark, %a1 197 moveq #.Lmark_sequence_len, %d4 198 bsr .Lmfm_mark_check 199 tstl %d1 200 bne .Ldata_exit 201 202 /* read data */ 203 204 movel #.Lsector_size - 1, %d4 /* sector size */ 205 movew #.Lmax_retry, %d2 206.Lread_data_loop: 207 moveb %a2@, %d5 208 andb #(.Lhr_fifo_1byte + .Lhr_fifo_2bytes), %d5 209 dbne %d2, .Lread_data_loop 210 beq .Ldata_exit 211 212 moveq #.Lmax_retry, %d2 213 moveb %a5@, %d3 214 bsr .Lmaybe_store 215 dbra %d4, 1f 216 bra .Ldata_crc0 2171: andb #.Lhr_fifo_2bytes, %d5 218 beq .Lread_data_loop 219 moveb %a5@, %d3 220 bsr .Lmaybe_store 221 dbra %d4, .Lread_data_loop 222 223 /* read CRC */ 224 225 movew #.Lmax_retry, %d2 226.Ldata_crc0: 227 tstb %a2@ 228 dbmi %d2, .Ldata_crc0 229 bpl .Ldata_exit 230 231 moveb %a5@, %d5 232 233 moveq #.Lmax_retry, %d2 234.Ldata_crc1: 235 tstb %a2@ 236 dbmi %d2, .Ldata_crc1 237 bpl .Ldata_exit 238 239 moveb %a5@, %d5 240 241 moveb %a2@, %d5 242 andb #.Lhr_crc_error, %d5 243 bne .Ldata_exit 244 245 /* return number of bytes read */ 246 247 movel #.Lsector_size, %d0 248 addw #1, %d4 249 subl %d4, %d0 250 251.Ldata_exit: 252 moveb #.Lmr_write_action, %a3@(.Lwrite_mode0 - .Lread_mark) 253 rts 254 255.Lmaybe_store: 256 tstl %a4 257 beq 9f 258 moveb %d3, %a4@+ 2599: rts 260