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