various bugfixes
[cor_2_6_31.git] / drivers / block / swim_asm.S
blobc9668206857bc6314223c1f4e4414d1d06404bd9
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  */
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
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
45         .equ    seek_time, 30000
46         .equ    max_retry, 40
47         .equ    sector_size, 512
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
59 sector_address_mark:
60         .byte   0xa1, 0xa1, 0xa1, 0xfe
61 sector_data_mark:
62         .byte   0xa1, 0xa1, 0xa1, 0xfb
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
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)
79         lea     sector_address_mark, %a0
80         moveq   #3, %d1
82 wait_addr_mark_byte:
84         tstb    %a2@
85         dbmi    %d2, wait_addr_mark_byte
86         bpl     header_exit
88         moveb   %a3@, %d3
89         cmpb    %a0@+, %d3
90         dbne    %d1, wait_addr_mark_byte
91         bne     wait_header_init
93         moveq   #max_retry, %d2
95 amark0: tstb    %a2@
96         dbmi    %d2, amark0
97         bpl     signal_nonyb
99         moveb   %a3@, %a4@(o_track)
101         moveq   #max_retry, %d2
103 amark1: tstb    %a2@
104         dbmi    %d2, amark1
105         bpl     signal_nonyb
107         moveb   %a3@, %a4@(o_side)
109         moveq   #max_retry, %d2
111 amark2: tstb    %a2@
112         dbmi    %d2, amark2
113         bpl     signal_nonyb
115         moveb   %a3@, %a4@(o_sector)
117         moveq   #max_retry, %d2
119 amark3: tstb    %a2@
120         dbmi    %d2, amark3
121         bpl     signal_nonyb
123         moveb   %a3@, %a4@(o_size)
125         moveq   #max_retry, %d2
127 crc0:   tstb    %a2@
128         dbmi    %d2, crc0
129         bpl     signal_nonyb
131         moveb   %a3@, %a4@(o_crc0)
133         moveq   #max_retry, %d2
135 crc1:   tstb    %a2@
136         dbmi    %d2, crc1
137         bpl     signal_nonyb
139         moveb   %a3@, %a4@(o_crc1)
141         tstb    %a3@(read_error - read_mark)
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
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
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
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)
177         lea     sector_data_mark, %a0
178         moveq   #3, %d1
180         /* wait data address mark */
182 wait_data_mark_byte:
184         tstb    %a2@
185         dbmi    %d2, wait_data_mark_byte
186         bpl     data_exit
188         moveb   %a3@, %d3
189         cmpb    %a0@+, %d3
190         dbne    %d1, wait_data_mark_byte
191         bne     wait_data_init
193         /* read data */
195         tstb    %a3@(read_error - read_mark)
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:
213         /* read CRC */
215         movew   #max_retry, %d2
216 data_crc0:
218         tstb    %a2@
219         dbmi    %d2, data_crc0
220         bpl     data_exit
222         moveb   %a3@, %d5
224         moveq   #max_retry, %d2
226 data_crc1:
228         tstb    %a2@
229         dbmi    %d2, data_crc1
230         bpl     data_exit
232         moveb   %a3@, %d5
234         tstb    %a3@(read_error - read_mark)
236         moveb   #0x18, %a3@(write_mode0 - read_mark)
238         /* return number of bytes read */
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