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