Merge branch 'for-5.15/logitech' into for-linus
[linux-2.6-microblaze.git] / drivers / block / swim_asm.S
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