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