18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * low-level functions for the SWIM floppy controller
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * needs assembly language because is very timing dependent
68c2ecf20Sopenharmony_ci * this controller exists only on macintosh 680x0 based
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2004,2008 Laurent Vivier <Laurent@lvivier.info>
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * based on Alastair Bridgewater SWIM analysis, 2001
118c2ecf20Sopenharmony_ci * based on netBSD IWM driver (c) 1997, 1998 Hauke Fath.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * 2004-08-21 (lv) - Initial implementation
148c2ecf20Sopenharmony_ci * 2008-11-05 (lv) - add get_swim_mode
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci	.equ	write_data,	0x0000
188c2ecf20Sopenharmony_ci	.equ	write_mark,	0x0200
198c2ecf20Sopenharmony_ci	.equ	write_CRC,	0x0400
208c2ecf20Sopenharmony_ci	.equ	write_parameter,0x0600
218c2ecf20Sopenharmony_ci	.equ	write_phase,	0x0800
228c2ecf20Sopenharmony_ci	.equ	write_setup,	0x0a00
238c2ecf20Sopenharmony_ci	.equ	write_mode0,	0x0c00
248c2ecf20Sopenharmony_ci	.equ	write_mode1,	0x0e00
258c2ecf20Sopenharmony_ci	.equ	read_data,	0x1000
268c2ecf20Sopenharmony_ci	.equ	read_mark,	0x1200
278c2ecf20Sopenharmony_ci	.equ	read_error,	0x1400
288c2ecf20Sopenharmony_ci	.equ	read_parameter,	0x1600
298c2ecf20Sopenharmony_ci	.equ	read_phase,	0x1800
308c2ecf20Sopenharmony_ci	.equ	read_setup,	0x1a00
318c2ecf20Sopenharmony_ci	.equ	read_status,	0x1c00
328c2ecf20Sopenharmony_ci	.equ	read_handshake,	0x1e00
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	.equ	o_side, 0
358c2ecf20Sopenharmony_ci	.equ	o_track, 1
368c2ecf20Sopenharmony_ci	.equ	o_sector, 2
378c2ecf20Sopenharmony_ci	.equ	o_size, 3
388c2ecf20Sopenharmony_ci	.equ	o_crc0, 4
398c2ecf20Sopenharmony_ci	.equ	o_crc1, 5
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	.equ	seek_time, 30000
428c2ecf20Sopenharmony_ci	.equ	max_retry, 40
438c2ecf20Sopenharmony_ci	.equ	sector_size, 512
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	.global swim_read_sector_header
468c2ecf20Sopenharmony_ciswim_read_sector_header:
478c2ecf20Sopenharmony_ci	link	%a6, #0
488c2ecf20Sopenharmony_ci	moveml	%d1-%d5/%a0-%a4,%sp@-
498c2ecf20Sopenharmony_ci	movel	%a6@(0x0c), %a4
508c2ecf20Sopenharmony_ci	bsr	mfm_read_addrmark
518c2ecf20Sopenharmony_ci	moveml	%sp@+, %d1-%d5/%a0-%a4
528c2ecf20Sopenharmony_ci	unlk	%a6
538c2ecf20Sopenharmony_ci	rts
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cisector_address_mark:
568c2ecf20Sopenharmony_ci	.byte	0xa1, 0xa1, 0xa1, 0xfe
578c2ecf20Sopenharmony_cisector_data_mark:
588c2ecf20Sopenharmony_ci	.byte	0xa1, 0xa1, 0xa1, 0xfb
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cimfm_read_addrmark:
618c2ecf20Sopenharmony_ci	movel	%a6@(0x08), %a3
628c2ecf20Sopenharmony_ci	lea	%a3@(read_handshake), %a2
638c2ecf20Sopenharmony_ci	lea	%a3@(read_mark), %a3
648c2ecf20Sopenharmony_ci	moveq	#-1, %d0
658c2ecf20Sopenharmony_ci	movew	#seek_time, %d2
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ciwait_header_init:
688c2ecf20Sopenharmony_ci	tstb	%a3@(read_error - read_mark)
698c2ecf20Sopenharmony_ci	moveb	#0x18, %a3@(write_mode0 - read_mark)
708c2ecf20Sopenharmony_ci	moveb	#0x01, %a3@(write_mode1 - read_mark)
718c2ecf20Sopenharmony_ci	moveb	#0x01, %a3@(write_mode0 - read_mark)
728c2ecf20Sopenharmony_ci	tstb	%a3@(read_error - read_mark)
738c2ecf20Sopenharmony_ci	moveb	#0x08, %a3@(write_mode1 - read_mark)
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	lea	sector_address_mark, %a0
768c2ecf20Sopenharmony_ci	moveq	#3, %d1
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ciwait_addr_mark_byte:
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	tstb	%a2@
818c2ecf20Sopenharmony_ci	dbmi	%d2, wait_addr_mark_byte
828c2ecf20Sopenharmony_ci	bpl	header_exit
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	moveb	%a3@, %d3
858c2ecf20Sopenharmony_ci	cmpb	%a0@+, %d3
868c2ecf20Sopenharmony_ci	dbne	%d1, wait_addr_mark_byte
878c2ecf20Sopenharmony_ci	bne	wait_header_init
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	moveq	#max_retry, %d2
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ciamark0:	tstb	%a2@
928c2ecf20Sopenharmony_ci	dbmi	%d2, amark0
938c2ecf20Sopenharmony_ci	bpl	signal_nonyb
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	moveb	%a3@, %a4@(o_track)
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	moveq	#max_retry, %d2
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ciamark1:	tstb	%a2@
1008c2ecf20Sopenharmony_ci	dbmi	%d2, amark1
1018c2ecf20Sopenharmony_ci	bpl	signal_nonyb
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	moveb	%a3@, %a4@(o_side)
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	moveq	#max_retry, %d2
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ciamark2:	tstb	%a2@
1088c2ecf20Sopenharmony_ci	dbmi	%d2, amark2
1098c2ecf20Sopenharmony_ci	bpl	signal_nonyb
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	moveb	%a3@, %a4@(o_sector)
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	moveq	#max_retry, %d2
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ciamark3:	tstb	%a2@
1168c2ecf20Sopenharmony_ci	dbmi	%d2, amark3
1178c2ecf20Sopenharmony_ci	bpl	signal_nonyb
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	moveb	%a3@, %a4@(o_size)
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	moveq	#max_retry, %d2
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cicrc0:	tstb	%a2@
1248c2ecf20Sopenharmony_ci	dbmi	%d2, crc0
1258c2ecf20Sopenharmony_ci	bpl	signal_nonyb
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	moveb	%a3@, %a4@(o_crc0)
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	moveq	#max_retry, %d2
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cicrc1:	tstb	%a2@
1328c2ecf20Sopenharmony_ci	dbmi	%d2, crc1
1338c2ecf20Sopenharmony_ci	bpl	signal_nonyb
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	moveb	%a3@, %a4@(o_crc1)
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	tstb	%a3@(read_error - read_mark)
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ciheader_exit:
1408c2ecf20Sopenharmony_ci	moveq	#0, %d0
1418c2ecf20Sopenharmony_ci	moveb	#0x18, %a3@(write_mode0 - read_mark)
1428c2ecf20Sopenharmony_ci	rts
1438c2ecf20Sopenharmony_cisignal_nonyb:
1448c2ecf20Sopenharmony_ci	moveq	#-1, %d0
1458c2ecf20Sopenharmony_ci	moveb	#0x18, %a3@(write_mode0 - read_mark)
1468c2ecf20Sopenharmony_ci	rts
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	.global swim_read_sector_data
1498c2ecf20Sopenharmony_ciswim_read_sector_data:
1508c2ecf20Sopenharmony_ci	link	%a6, #0
1518c2ecf20Sopenharmony_ci	moveml	%d1-%d5/%a0-%a5,%sp@-
1528c2ecf20Sopenharmony_ci	movel	%a6@(0x0c), %a4
1538c2ecf20Sopenharmony_ci	bsr	mfm_read_data
1548c2ecf20Sopenharmony_ci	moveml	%sp@+, %d1-%d5/%a0-%a5
1558c2ecf20Sopenharmony_ci	unlk	%a6
1568c2ecf20Sopenharmony_ci	rts
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cimfm_read_data:
1598c2ecf20Sopenharmony_ci	movel	%a6@(0x08), %a3
1608c2ecf20Sopenharmony_ci	lea	%a3@(read_handshake), %a2
1618c2ecf20Sopenharmony_ci	lea	%a3@(read_data), %a5
1628c2ecf20Sopenharmony_ci	lea	%a3@(read_mark), %a3
1638c2ecf20Sopenharmony_ci	movew	#seek_time, %d2
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ciwait_data_init:
1668c2ecf20Sopenharmony_ci	tstb	%a3@(read_error - read_mark)
1678c2ecf20Sopenharmony_ci	moveb	#0x18, %a3@(write_mode0 - read_mark)
1688c2ecf20Sopenharmony_ci	moveb	#0x01, %a3@(write_mode1 - read_mark)
1698c2ecf20Sopenharmony_ci	moveb	#0x01, %a3@(write_mode0 - read_mark)
1708c2ecf20Sopenharmony_ci	tstb	%a3@(read_error - read_mark)
1718c2ecf20Sopenharmony_ci	moveb	#0x08, %a3@(write_mode1 - read_mark)
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	lea	sector_data_mark, %a0
1748c2ecf20Sopenharmony_ci	moveq	#3, %d1
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	/* wait data address mark */
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ciwait_data_mark_byte:
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	tstb	%a2@
1818c2ecf20Sopenharmony_ci	dbmi	%d2, wait_data_mark_byte
1828c2ecf20Sopenharmony_ci	bpl	data_exit
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	moveb	%a3@, %d3
1858c2ecf20Sopenharmony_ci	cmpb	%a0@+, %d3
1868c2ecf20Sopenharmony_ci	dbne	%d1, wait_data_mark_byte
1878c2ecf20Sopenharmony_ci	bne	wait_data_init
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	/* read data */
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	tstb	%a3@(read_error - read_mark)
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	movel	#sector_size-1, %d4		/* sector size */
1948c2ecf20Sopenharmony_ciread_new_data:
1958c2ecf20Sopenharmony_ci	movew	#max_retry, %d2
1968c2ecf20Sopenharmony_ciread_data_loop:
1978c2ecf20Sopenharmony_ci	moveb	%a2@, %d5
1988c2ecf20Sopenharmony_ci	andb	#0xc0, %d5
1998c2ecf20Sopenharmony_ci	dbne	%d2, read_data_loop
2008c2ecf20Sopenharmony_ci	beq	data_exit
2018c2ecf20Sopenharmony_ci	moveb	%a5@, %a4@+
2028c2ecf20Sopenharmony_ci	andb	#0x40, %d5
2038c2ecf20Sopenharmony_ci	dbne	%d4, read_new_data
2048c2ecf20Sopenharmony_ci	beq	exit_loop
2058c2ecf20Sopenharmony_ci	moveb	%a5@, %a4@+
2068c2ecf20Sopenharmony_ci	dbra	%d4, read_new_data
2078c2ecf20Sopenharmony_ciexit_loop:
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	/* read CRC */
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	movew	#max_retry, %d2
2128c2ecf20Sopenharmony_cidata_crc0:
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	tstb	%a2@
2158c2ecf20Sopenharmony_ci	dbmi	%d2, data_crc0
2168c2ecf20Sopenharmony_ci	bpl	data_exit
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	moveb	%a3@, %d5
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	moveq	#max_retry, %d2
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_cidata_crc1:
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	tstb	%a2@
2258c2ecf20Sopenharmony_ci	dbmi	%d2, data_crc1
2268c2ecf20Sopenharmony_ci	bpl	data_exit
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	moveb	%a3@, %d5
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	tstb	%a3@(read_error - read_mark)
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	moveb	#0x18, %a3@(write_mode0 - read_mark)
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	/* return number of bytes read */
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	movel	#sector_size, %d0
2378c2ecf20Sopenharmony_ci	addw	#1, %d4
2388c2ecf20Sopenharmony_ci	subl	%d4, %d0
2398c2ecf20Sopenharmony_ci	rts
2408c2ecf20Sopenharmony_cidata_exit:
2418c2ecf20Sopenharmony_ci	moveb	#0x18, %a3@(write_mode0 - read_mark)
2428c2ecf20Sopenharmony_ci	moveq	#-1, %d0
2438c2ecf20Sopenharmony_ci	rts
244