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 |
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 | |
55 | sector_address_mark: |
56 | .byte 0xa1, 0xa1, 0xa1, 0xfe |
57 | sector_data_mark: |
58 | .byte 0xa1, 0xa1, 0xa1, 0xfb |
59 | |
60 | mfm_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 | |
67 | wait_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 | |
78 | wait_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 | |
91 | amark0: tstb %a2@ |
92 | dbmi %d2, amark0 |
93 | bpl signal_nonyb |
94 | |
95 | moveb %a3@, %a4@(o_track) |
96 | |
97 | moveq #max_retry, %d2 |
98 | |
99 | amark1: tstb %a2@ |
100 | dbmi %d2, amark1 |
101 | bpl signal_nonyb |
102 | |
103 | moveb %a3@, %a4@(o_side) |
104 | |
105 | moveq #max_retry, %d2 |
106 | |
107 | amark2: tstb %a2@ |
108 | dbmi %d2, amark2 |
109 | bpl signal_nonyb |
110 | |
111 | moveb %a3@, %a4@(o_sector) |
112 | |
113 | moveq #max_retry, %d2 |
114 | |
115 | amark3: tstb %a2@ |
116 | dbmi %d2, amark3 |
117 | bpl signal_nonyb |
118 | |
119 | moveb %a3@, %a4@(o_size) |
120 | |
121 | moveq #max_retry, %d2 |
122 | |
123 | crc0: tstb %a2@ |
124 | dbmi %d2, crc0 |
125 | bpl signal_nonyb |
126 | |
127 | moveb %a3@, %a4@(o_crc0) |
128 | |
129 | moveq #max_retry, %d2 |
130 | |
131 | crc1: 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 | |
139 | header_exit: |
140 | moveq #0, %d0 |
141 | moveb #0x18, %a3@(write_mode0 - read_mark) |
142 | rts |
143 | signal_nonyb: |
144 | moveq #-1, %d0 |
145 | moveb #0x18, %a3@(write_mode0 - read_mark) |
146 | rts |
147 | |
148 | .global swim_read_sector_data |
149 | swim_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 | |
158 | mfm_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 | |
165 | wait_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 | |
178 | wait_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 */ |
194 | read_new_data: |
195 | movew #max_retry, %d2 |
196 | read_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 |
207 | exit_loop: |
208 | |
209 | /* read CRC */ |
210 | |
211 | movew #max_retry, %d2 |
212 | data_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 | |
222 | data_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 |
240 | data_exit: |
241 | moveb #0x18, %a3@(write_mode0 - read_mark) |
242 | moveq #-1, %d0 |
243 | rts |
244 | |