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 write_data, 0x0000 18 .equ write_mark, 0x0200 19 .equ write_CRC, 0x0400 20 .equ write_parameter,0x0600 21 .equ write_phase, 0x0800 22 .equ write_setup, 0x0a00 23 .equ write_mode0, 0x0c00 24 .equ write_mode1, 0x0e00 25 .equ read_data, 0x1000 26 .equ read_mark, 0x1200 27 .equ read_error, 0x1400 28 .equ read_parameter, 0x1600 29 .equ read_phase, 0x1800 30 .equ read_setup, 0x1a00 31 .equ read_status, 0x1c00 32 .equ read_handshake, 0x1e00 33 34 .equ o_side, 0 35 .equ o_track, 1 36 .equ o_sector, 2 37 .equ o_size, 3 38 .equ o_crc0, 4 39 .equ o_crc1, 5 40 41 .equ seek_time, 30000 42 .equ max_retry, 40 43 .equ sector_size, 512 44 45 .global swim_read_sector_header 46swim_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 55sector_address_mark: 56 .byte 0xa1, 0xa1, 0xa1, 0xfe 57sector_data_mark: 58 .byte 0xa1, 0xa1, 0xa1, 0xfb 59 60mfm_read_addrmark: 61 movel %a6@(0x08), %a3 62 lea %a3@(read_handshake), %a2 63 lea %a3@(read_mark), %a3 64 moveq #-1, %d0 65 movew #seek_time, %d2 66 67wait_header_init: 68 tstb %a3@(read_error - read_mark) 69 moveb #0x18, %a3@(write_mode0 - read_mark) 70 moveb #0x01, %a3@(write_mode1 - read_mark) 71 moveb #0x01, %a3@(write_mode0 - read_mark) 72 tstb %a3@(read_error - read_mark) 73 moveb #0x08, %a3@(write_mode1 - read_mark) 74 75 lea sector_address_mark, %a0 76 moveq #3, %d1 77 78wait_addr_mark_byte: 79 80 tstb %a2@ 81 dbmi %d2, wait_addr_mark_byte 82 bpl header_exit 83 84 moveb %a3@, %d3 85 cmpb %a0@+, %d3 86 dbne %d1, wait_addr_mark_byte 87 bne wait_header_init 88 89 moveq #max_retry, %d2 90 91amark0: tstb %a2@ 92 dbmi %d2, amark0 93 bpl signal_nonyb 94 95 moveb %a3@, %a4@(o_track) 96 97 moveq #max_retry, %d2 98 99amark1: tstb %a2@ 100 dbmi %d2, amark1 101 bpl signal_nonyb 102 103 moveb %a3@, %a4@(o_side) 104 105 moveq #max_retry, %d2 106 107amark2: tstb %a2@ 108 dbmi %d2, amark2 109 bpl signal_nonyb 110 111 moveb %a3@, %a4@(o_sector) 112 113 moveq #max_retry, %d2 114 115amark3: tstb %a2@ 116 dbmi %d2, amark3 117 bpl signal_nonyb 118 119 moveb %a3@, %a4@(o_size) 120 121 moveq #max_retry, %d2 122 123crc0: tstb %a2@ 124 dbmi %d2, crc0 125 bpl signal_nonyb 126 127 moveb %a3@, %a4@(o_crc0) 128 129 moveq #max_retry, %d2 130 131crc1: tstb %a2@ 132 dbmi %d2, crc1 133 bpl signal_nonyb 134 135 moveb %a3@, %a4@(o_crc1) 136 137 tstb %a3@(read_error - read_mark) 138 139header_exit: 140 moveq #0, %d0 141 moveb #0x18, %a3@(write_mode0 - read_mark) 142 rts 143signal_nonyb: 144 moveq #-1, %d0 145 moveb #0x18, %a3@(write_mode0 - read_mark) 146 rts 147 148 .global swim_read_sector_data 149swim_read_sector_data: 150 link %a6, #0 151 moveml %d1-%d5/%a0-%a5,%sp@- 152 movel %a6@(0x0c), %a4 153 bsr mfm_read_data 154 moveml %sp@+, %d1-%d5/%a0-%a5 155 unlk %a6 156 rts 157 158mfm_read_data: 159 movel %a6@(0x08), %a3 160 lea %a3@(read_handshake), %a2 161 lea %a3@(read_data), %a5 162 lea %a3@(read_mark), %a3 163 movew #seek_time, %d2 164 165wait_data_init: 166 tstb %a3@(read_error - read_mark) 167 moveb #0x18, %a3@(write_mode0 - read_mark) 168 moveb #0x01, %a3@(write_mode1 - read_mark) 169 moveb #0x01, %a3@(write_mode0 - read_mark) 170 tstb %a3@(read_error - read_mark) 171 moveb #0x08, %a3@(write_mode1 - read_mark) 172 173 lea sector_data_mark, %a0 174 moveq #3, %d1 175 176 /* wait data address mark */ 177 178wait_data_mark_byte: 179 180 tstb %a2@ 181 dbmi %d2, wait_data_mark_byte 182 bpl data_exit 183 184 moveb %a3@, %d3 185 cmpb %a0@+, %d3 186 dbne %d1, wait_data_mark_byte 187 bne wait_data_init 188 189 /* read data */ 190 191 tstb %a3@(read_error - read_mark) 192 193 movel #sector_size-1, %d4 /* sector size */ 194read_new_data: 195 movew #max_retry, %d2 196read_data_loop: 197 moveb %a2@, %d5 198 andb #0xc0, %d5 199 dbne %d2, read_data_loop 200 beq data_exit 201 moveb %a5@, %a4@+ 202 andb #0x40, %d5 203 dbne %d4, read_new_data 204 beq exit_loop 205 moveb %a5@, %a4@+ 206 dbra %d4, read_new_data 207exit_loop: 208 209 /* read CRC */ 210 211 movew #max_retry, %d2 212data_crc0: 213 214 tstb %a2@ 215 dbmi %d2, data_crc0 216 bpl data_exit 217 218 moveb %a3@, %d5 219 220 moveq #max_retry, %d2 221 222data_crc1: 223 224 tstb %a2@ 225 dbmi %d2, data_crc1 226 bpl data_exit 227 228 moveb %a3@, %d5 229 230 tstb %a3@(read_error - read_mark) 231 232 moveb #0x18, %a3@(write_mode0 - read_mark) 233 234 /* return number of bytes read */ 235 236 movel #sector_size, %d0 237 addw #1, %d4 238 subl %d4, %d0 239 rts 240data_exit: 241 moveb #0x18, %a3@(write_mode0 - read_mark) 242 moveq #-1, %d0 243 rts 244