xref: /linux/drivers/block/swim_asm.S (revision e7a6727deab0d300171ee059b7dbcdbdb3c46797)
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	.Lwrite_data,		0x0000
18	.equ	.Lwrite_mark,		0x0200
19	.equ	.Lwrite_CRC,		0x0400
20	.equ	.Lwrite_parameter,	0x0600
21	.equ	.Lwrite_phase,		0x0800
22	.equ	.Lwrite_setup,		0x0a00
23	.equ	.Lwrite_mode0,		0x0c00
24	.equ	.Lwrite_mode1,		0x0e00
25	.equ	.Lread_data,		0x1000
26	.equ	.Lread_mark,		0x1200
27	.equ	.Lread_error,		0x1400
28	.equ	.Lread_parameter,	0x1600
29	.equ	.Lread_phase,		0x1800
30	.equ	.Lread_setup,		0x1a00
31	.equ	.Lread_status,		0x1c00
32	.equ	.Lread_handshake,	0x1e00
33
34	.equ	.Lo_side,		0
35	.equ	.Lo_track,		1
36	.equ	.Lo_sector,		2
37	.equ	.Lo_size,		3
38	.equ	.Lo_crc0,		4
39	.equ	.Lo_crc1,		5
40
41	.equ	.Lseek_time,		30000
42	.equ	.Lmax_retry,		40
43	.equ	.Lsector_size,		512
44	.equ	.Lmark_sequence_len,	4
45
46	.equ	.Lmr_clear_fifo,	0x01
47	.equ	.Lmr_action,		0x08
48	.equ	.Lmr_write_action,	0x18
49
50	.equ	.Lhr_crc_error,		0x02
51	.equ	.Lhr_fifo_2bytes,	0x40
52	.equ	.Lhr_fifo_1byte,	0x80
53
54.Lmfm_mark_check:
55	/*
56	 * This subroutine reads and validates a mark byte sequence.
57	 * On entry, %a1 and %d4 shall hold the location and length (resp.)
58	 * of the mark byte array.
59	 * %a2 and %a3 shall hold the locations of the handshake and mark
60	 * registers.
61	 * Returns zero in %d1 for success.
62	 */
63
64	moveq	#-1, %d1
65	subq	#1, %d4
66	movew	#.Lseek_time, %d2
67
685:	tstb	%a2@
69	dbmi	%d2, 5b
70	bpl	6f
71
72	moveb	%a3@, %d3
73	cmpb	%a1@+, %d3
74	dbne	%d4, 5b
75	bne	6f
76
77	moveq	#0, %d1
786:	rts
79
80	.global swim_read_sector_header
81swim_read_sector_header:
82	link	%a6, #0
83	moveml	%d1-%d5/%a0-%a5,%sp@-
84	movel	%a6@(0x0c), %a4
85	moveq	#-1, %d0
86	bsr	.Lmfm_read_header
87	moveml	%sp@+, %d1-%d5/%a0-%a5
88	unlk	%a6
89	rts
90
91.Lsector_address_mark:
92	.byte	0xa1, 0xa1, 0xa1, 0xfe
93.Lsector_data_mark:
94	.byte	0xa1, 0xa1, 0xa1, 0xfb
95
96.Lmfm_read_header:
97	movel	%a6@(0x08), %a3
98	lea	%a3@(.Lread_handshake), %a2
99	lea	%a3@(.Lread_data), %a5
100	lea	%a3@(.Lread_mark), %a3
101
102	moveb	#.Lmr_write_action, %a3@(.Lwrite_mode0 - .Lread_mark)
103	moveb	#.Lmr_clear_fifo, %a3@(.Lwrite_mode1 - .Lread_mark)
104	moveb	#.Lmr_clear_fifo, %a3@(.Lwrite_mode0 - .Lread_mark)
105	tstb	%a3@(.Lread_error - .Lread_mark)
106	moveb	#.Lmr_action, %a3@(.Lwrite_mode1 - .Lread_mark)
107
108	lea	.Lsector_address_mark, %a1
109	moveq	#.Lmark_sequence_len, %d4
110	bsr	.Lmfm_mark_check
111	tstl	%d1
112	bne	.Lsignal_nonyb
113
114	/* read header */
115
116	moveq	#.Lmax_retry, %d2
117.Lamark0:
118	tstb	%a2@
119	dbmi	%d2, .Lamark0
120	bpl	.Lsignal_nonyb
121
122	moveb	%a5@, %a4@(.Lo_track)
123
124	moveq	#.Lmax_retry, %d2
125.Lamark1:
126	tstb	%a2@
127	dbmi	%d2, .Lamark1
128	bpl	.Lsignal_nonyb
129
130	moveb	%a5@, %a4@(.Lo_side)
131
132	moveq	#.Lmax_retry, %d2
133.Lamark2:
134	tstb	%a2@
135	dbmi	%d2, .Lamark2
136	bpl	.Lsignal_nonyb
137
138	moveb	%a5@, %a4@(.Lo_sector)
139
140	moveq	#.Lmax_retry, %d2
141.Lamark3:
142	tstb	%a2@
143	dbmi	%d2, .Lamark3
144	bpl	.Lsignal_nonyb
145
146	moveb	%a5@, %a4@(.Lo_size)
147
148	moveq	#.Lmax_retry, %d2
149.Lcrc0:
150	tstb	%a2@
151	dbmi	%d2, .Lcrc0
152	bpl	.Lsignal_nonyb
153
154	moveb	%a5@, %a4@(.Lo_crc0)
155
156	moveq	#.Lmax_retry, %d2
157.Lcrc1:
158	tstb	%a2@
159	dbmi	%d2, .Lcrc1
160	bpl	.Lsignal_nonyb
161
162	moveb	%a5@, %a4@(.Lo_crc1)
163
164	moveb	%a2@, %d5
165	andb	#.Lhr_crc_error, %d5
166	bne	.Lsignal_nonyb
167
168	moveq	#0, %d0
169.Lsignal_nonyb:
170	moveb	#.Lmr_write_action, %a3@(.Lwrite_mode0 - .Lread_mark)
171	rts
172
173	.global swim_read_sector_data
174swim_read_sector_data:
175	link	%a6, #0
176	moveml	%d1-%d5/%a0-%a5,%sp@-
177	movel	%a6@(0x0c), %a4
178	moveq	#-1, %d0
179	bsr	.Lmfm_read_data
180	moveml	%sp@+, %d1-%d5/%a0-%a5
181	unlk	%a6
182	rts
183
184.Lmfm_read_data:
185	movel	%a6@(0x08), %a3
186	lea	%a3@(.Lread_handshake), %a2
187	lea	%a3@(.Lread_data), %a5
188	lea	%a3@(.Lread_mark), %a3
189
190	moveb	#.Lmr_write_action, %a3@(.Lwrite_mode0 - .Lread_mark)
191	moveb	#.Lmr_clear_fifo, %a3@(.Lwrite_mode1 - .Lread_mark)
192	moveb	#.Lmr_clear_fifo, %a3@(.Lwrite_mode0 - .Lread_mark)
193	tstb	%a3@(.Lread_error - .Lread_mark)
194	moveb	#.Lmr_action, %a3@(.Lwrite_mode1 - .Lread_mark)
195
196	lea	.Lsector_data_mark, %a1
197	moveq	#.Lmark_sequence_len, %d4
198	bsr	.Lmfm_mark_check
199	tstl	%d1
200	bne	.Ldata_exit
201
202	/* read data */
203
204	movel	#.Lsector_size - 1, %d4		/* sector size */
205	movew	#.Lmax_retry, %d2
206.Lread_data_loop:
207	moveb	%a2@, %d5
208	andb	#(.Lhr_fifo_1byte + .Lhr_fifo_2bytes), %d5
209	dbne	%d2, .Lread_data_loop
210	beq	.Ldata_exit
211
212	moveq	#.Lmax_retry, %d2
213	moveb	%a5@, %d3
214	bsr	.Lmaybe_store
215	dbra	%d4, 1f
216	bra	.Ldata_crc0
2171:	andb	#.Lhr_fifo_2bytes, %d5
218	beq	.Lread_data_loop
219	moveb	%a5@, %d3
220	bsr	.Lmaybe_store
221	dbra	%d4, .Lread_data_loop
222
223	/* read CRC */
224
225	movew	#.Lmax_retry, %d2
226.Ldata_crc0:
227	tstb	%a2@
228	dbmi	%d2, .Ldata_crc0
229	bpl	.Ldata_exit
230
231	moveb	%a5@, %d5
232
233	moveq	#.Lmax_retry, %d2
234.Ldata_crc1:
235	tstb	%a2@
236	dbmi	%d2, .Ldata_crc1
237	bpl	.Ldata_exit
238
239	moveb	%a5@, %d5
240
241	moveb	%a2@, %d5
242	andb	#.Lhr_crc_error, %d5
243	bne	.Ldata_exit
244
245	/* return number of bytes read */
246
247	movel	#.Lsector_size, %d0
248	addw	#1, %d4
249	subl	%d4, %d0
250
251.Ldata_exit:
252	moveb	#.Lmr_write_action, %a3@(.Lwrite_mode0 - .Lread_mark)
253	rts
254
255.Lmaybe_store:
256	tstl	%a4
257	beq	9f
258	moveb	%d3, %a4@+
2599:	rts
260