Loading...
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
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