sgi-xpc: prevent false heartbeat failures
[linux-2.6] / drivers / block / swim_asm.S
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
50 swim_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
59 sector_address_mark:
60         .byte   0xa1, 0xa1, 0xa1, 0xfe
61 sector_data_mark:
62         .byte   0xa1, 0xa1, 0xa1, 0xfb
63
64 mfm_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
71 wait_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
82 wait_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
95 amark0: tstb    %a2@
96         dbmi    %d2, amark0
97         bpl     signal_nonyb
98
99         moveb   %a3@, %a4@(o_track)
100
101         moveq   #max_retry, %d2
102
103 amark1: tstb    %a2@
104         dbmi    %d2, amark1
105         bpl     signal_nonyb
106
107         moveb   %a3@, %a4@(o_side)
108
109         moveq   #max_retry, %d2
110
111 amark2: tstb    %a2@
112         dbmi    %d2, amark2
113         bpl     signal_nonyb
114
115         moveb   %a3@, %a4@(o_sector)
116
117         moveq   #max_retry, %d2
118
119 amark3: tstb    %a2@
120         dbmi    %d2, amark3
121         bpl     signal_nonyb
122
123         moveb   %a3@, %a4@(o_size)
124
125         moveq   #max_retry, %d2
126
127 crc0:   tstb    %a2@
128         dbmi    %d2, crc0
129         bpl     signal_nonyb
130
131         moveb   %a3@, %a4@(o_crc0)
132
133         moveq   #max_retry, %d2
134
135 crc1:   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
143 header_exit:
144         moveq   #0, %d0
145         moveb   #0x18, %a3@(write_mode0 - read_mark)
146         rts
147 signal_nonyb:
148         moveq   #-1, %d0
149         moveb   #0x18, %a3@(write_mode0 - read_mark)
150         rts
151
152         .global swim_read_sector_data
153 swim_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
162 mfm_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
169 wait_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
182 wait_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 */
198 read_new_data:
199         movew   #max_retry, %d2
200 read_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
211 exit_loop:
212
213         /* read CRC */
214
215         movew   #max_retry, %d2
216 data_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
226 data_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
244 data_exit:
245         moveb   #0x18, %a3@(write_mode0 - read_mark)
246         moveq   #-1, %d0
247         rts