1*2874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */ 28852ecd9SLaurent Vivier/* 38852ecd9SLaurent Vivier * low-level functions for the SWIM floppy controller 48852ecd9SLaurent Vivier * 58852ecd9SLaurent Vivier * needs assembly language because is very timing dependent 68852ecd9SLaurent Vivier * this controller exists only on macintosh 680x0 based 78852ecd9SLaurent Vivier * 88852ecd9SLaurent Vivier * Copyright (C) 2004,2008 Laurent Vivier <Laurent@lvivier.info> 98852ecd9SLaurent Vivier * 108852ecd9SLaurent Vivier * based on Alastair Bridgewater SWIM analysis, 2001 118852ecd9SLaurent Vivier * based on netBSD IWM driver (c) 1997, 1998 Hauke Fath. 128852ecd9SLaurent Vivier * 138852ecd9SLaurent Vivier * 2004-08-21 (lv) - Initial implementation 148852ecd9SLaurent Vivier * 2008-11-05 (lv) - add get_swim_mode 158852ecd9SLaurent Vivier */ 168852ecd9SLaurent Vivier 178852ecd9SLaurent Vivier .equ write_data, 0x0000 188852ecd9SLaurent Vivier .equ write_mark, 0x0200 198852ecd9SLaurent Vivier .equ write_CRC, 0x0400 208852ecd9SLaurent Vivier .equ write_parameter,0x0600 218852ecd9SLaurent Vivier .equ write_phase, 0x0800 228852ecd9SLaurent Vivier .equ write_setup, 0x0a00 238852ecd9SLaurent Vivier .equ write_mode0, 0x0c00 248852ecd9SLaurent Vivier .equ write_mode1, 0x0e00 258852ecd9SLaurent Vivier .equ read_data, 0x1000 268852ecd9SLaurent Vivier .equ read_mark, 0x1200 278852ecd9SLaurent Vivier .equ read_error, 0x1400 288852ecd9SLaurent Vivier .equ read_parameter, 0x1600 298852ecd9SLaurent Vivier .equ read_phase, 0x1800 308852ecd9SLaurent Vivier .equ read_setup, 0x1a00 318852ecd9SLaurent Vivier .equ read_status, 0x1c00 328852ecd9SLaurent Vivier .equ read_handshake, 0x1e00 338852ecd9SLaurent Vivier 348852ecd9SLaurent Vivier .equ o_side, 0 358852ecd9SLaurent Vivier .equ o_track, 1 368852ecd9SLaurent Vivier .equ o_sector, 2 378852ecd9SLaurent Vivier .equ o_size, 3 388852ecd9SLaurent Vivier .equ o_crc0, 4 398852ecd9SLaurent Vivier .equ o_crc1, 5 408852ecd9SLaurent Vivier 418852ecd9SLaurent Vivier .equ seek_time, 30000 428852ecd9SLaurent Vivier .equ max_retry, 40 438852ecd9SLaurent Vivier .equ sector_size, 512 448852ecd9SLaurent Vivier 458852ecd9SLaurent Vivier .global swim_read_sector_header 468852ecd9SLaurent Vivierswim_read_sector_header: 478852ecd9SLaurent Vivier link %a6, #0 488852ecd9SLaurent Vivier moveml %d1-%d5/%a0-%a4,%sp@- 498852ecd9SLaurent Vivier movel %a6@(0x0c), %a4 508852ecd9SLaurent Vivier bsr mfm_read_addrmark 518852ecd9SLaurent Vivier moveml %sp@+, %d1-%d5/%a0-%a4 528852ecd9SLaurent Vivier unlk %a6 538852ecd9SLaurent Vivier rts 548852ecd9SLaurent Vivier 558852ecd9SLaurent Viviersector_address_mark: 568852ecd9SLaurent Vivier .byte 0xa1, 0xa1, 0xa1, 0xfe 578852ecd9SLaurent Viviersector_data_mark: 588852ecd9SLaurent Vivier .byte 0xa1, 0xa1, 0xa1, 0xfb 598852ecd9SLaurent Vivier 608852ecd9SLaurent Viviermfm_read_addrmark: 618852ecd9SLaurent Vivier movel %a6@(0x08), %a3 628852ecd9SLaurent Vivier lea %a3@(read_handshake), %a2 638852ecd9SLaurent Vivier lea %a3@(read_mark), %a3 648852ecd9SLaurent Vivier moveq #-1, %d0 658852ecd9SLaurent Vivier movew #seek_time, %d2 668852ecd9SLaurent Vivier 678852ecd9SLaurent Vivierwait_header_init: 688852ecd9SLaurent Vivier tstb %a3@(read_error - read_mark) 698852ecd9SLaurent Vivier moveb #0x18, %a3@(write_mode0 - read_mark) 708852ecd9SLaurent Vivier moveb #0x01, %a3@(write_mode1 - read_mark) 718852ecd9SLaurent Vivier moveb #0x01, %a3@(write_mode0 - read_mark) 728852ecd9SLaurent Vivier tstb %a3@(read_error - read_mark) 738852ecd9SLaurent Vivier moveb #0x08, %a3@(write_mode1 - read_mark) 748852ecd9SLaurent Vivier 758852ecd9SLaurent Vivier lea sector_address_mark, %a0 768852ecd9SLaurent Vivier moveq #3, %d1 778852ecd9SLaurent Vivier 788852ecd9SLaurent Vivierwait_addr_mark_byte: 798852ecd9SLaurent Vivier 808852ecd9SLaurent Vivier tstb %a2@ 818852ecd9SLaurent Vivier dbmi %d2, wait_addr_mark_byte 828852ecd9SLaurent Vivier bpl header_exit 838852ecd9SLaurent Vivier 848852ecd9SLaurent Vivier moveb %a3@, %d3 858852ecd9SLaurent Vivier cmpb %a0@+, %d3 868852ecd9SLaurent Vivier dbne %d1, wait_addr_mark_byte 878852ecd9SLaurent Vivier bne wait_header_init 888852ecd9SLaurent Vivier 898852ecd9SLaurent Vivier moveq #max_retry, %d2 908852ecd9SLaurent Vivier 918852ecd9SLaurent Vivieramark0: tstb %a2@ 928852ecd9SLaurent Vivier dbmi %d2, amark0 938852ecd9SLaurent Vivier bpl signal_nonyb 948852ecd9SLaurent Vivier 958852ecd9SLaurent Vivier moveb %a3@, %a4@(o_track) 968852ecd9SLaurent Vivier 978852ecd9SLaurent Vivier moveq #max_retry, %d2 988852ecd9SLaurent Vivier 998852ecd9SLaurent Vivieramark1: tstb %a2@ 1008852ecd9SLaurent Vivier dbmi %d2, amark1 1018852ecd9SLaurent Vivier bpl signal_nonyb 1028852ecd9SLaurent Vivier 1038852ecd9SLaurent Vivier moveb %a3@, %a4@(o_side) 1048852ecd9SLaurent Vivier 1058852ecd9SLaurent Vivier moveq #max_retry, %d2 1068852ecd9SLaurent Vivier 1078852ecd9SLaurent Vivieramark2: tstb %a2@ 1088852ecd9SLaurent Vivier dbmi %d2, amark2 1098852ecd9SLaurent Vivier bpl signal_nonyb 1108852ecd9SLaurent Vivier 1118852ecd9SLaurent Vivier moveb %a3@, %a4@(o_sector) 1128852ecd9SLaurent Vivier 1138852ecd9SLaurent Vivier moveq #max_retry, %d2 1148852ecd9SLaurent Vivier 1158852ecd9SLaurent Vivieramark3: tstb %a2@ 1168852ecd9SLaurent Vivier dbmi %d2, amark3 1178852ecd9SLaurent Vivier bpl signal_nonyb 1188852ecd9SLaurent Vivier 1198852ecd9SLaurent Vivier moveb %a3@, %a4@(o_size) 1208852ecd9SLaurent Vivier 1218852ecd9SLaurent Vivier moveq #max_retry, %d2 1228852ecd9SLaurent Vivier 1238852ecd9SLaurent Viviercrc0: tstb %a2@ 1248852ecd9SLaurent Vivier dbmi %d2, crc0 1258852ecd9SLaurent Vivier bpl signal_nonyb 1268852ecd9SLaurent Vivier 1278852ecd9SLaurent Vivier moveb %a3@, %a4@(o_crc0) 1288852ecd9SLaurent Vivier 1298852ecd9SLaurent Vivier moveq #max_retry, %d2 1308852ecd9SLaurent Vivier 1318852ecd9SLaurent Viviercrc1: tstb %a2@ 1328852ecd9SLaurent Vivier dbmi %d2, crc1 1338852ecd9SLaurent Vivier bpl signal_nonyb 1348852ecd9SLaurent Vivier 1358852ecd9SLaurent Vivier moveb %a3@, %a4@(o_crc1) 1368852ecd9SLaurent Vivier 1378852ecd9SLaurent Vivier tstb %a3@(read_error - read_mark) 1388852ecd9SLaurent Vivier 1398852ecd9SLaurent Vivierheader_exit: 1408852ecd9SLaurent Vivier moveq #0, %d0 1418852ecd9SLaurent Vivier moveb #0x18, %a3@(write_mode0 - read_mark) 1428852ecd9SLaurent Vivier rts 1438852ecd9SLaurent Viviersignal_nonyb: 1448852ecd9SLaurent Vivier moveq #-1, %d0 1458852ecd9SLaurent Vivier moveb #0x18, %a3@(write_mode0 - read_mark) 1468852ecd9SLaurent Vivier rts 1478852ecd9SLaurent Vivier 1488852ecd9SLaurent Vivier .global swim_read_sector_data 1498852ecd9SLaurent Vivierswim_read_sector_data: 1508852ecd9SLaurent Vivier link %a6, #0 1518852ecd9SLaurent Vivier moveml %d1-%d5/%a0-%a5,%sp@- 1528852ecd9SLaurent Vivier movel %a6@(0x0c), %a4 1538852ecd9SLaurent Vivier bsr mfm_read_data 1548852ecd9SLaurent Vivier moveml %sp@+, %d1-%d5/%a0-%a5 1558852ecd9SLaurent Vivier unlk %a6 1568852ecd9SLaurent Vivier rts 1578852ecd9SLaurent Vivier 1588852ecd9SLaurent Viviermfm_read_data: 1598852ecd9SLaurent Vivier movel %a6@(0x08), %a3 1608852ecd9SLaurent Vivier lea %a3@(read_handshake), %a2 1618852ecd9SLaurent Vivier lea %a3@(read_data), %a5 1628852ecd9SLaurent Vivier lea %a3@(read_mark), %a3 1638852ecd9SLaurent Vivier movew #seek_time, %d2 1648852ecd9SLaurent Vivier 1658852ecd9SLaurent Vivierwait_data_init: 1668852ecd9SLaurent Vivier tstb %a3@(read_error - read_mark) 1678852ecd9SLaurent Vivier moveb #0x18, %a3@(write_mode0 - read_mark) 1688852ecd9SLaurent Vivier moveb #0x01, %a3@(write_mode1 - read_mark) 1698852ecd9SLaurent Vivier moveb #0x01, %a3@(write_mode0 - read_mark) 1708852ecd9SLaurent Vivier tstb %a3@(read_error - read_mark) 1718852ecd9SLaurent Vivier moveb #0x08, %a3@(write_mode1 - read_mark) 1728852ecd9SLaurent Vivier 1738852ecd9SLaurent Vivier lea sector_data_mark, %a0 1748852ecd9SLaurent Vivier moveq #3, %d1 1758852ecd9SLaurent Vivier 1768852ecd9SLaurent Vivier /* wait data address mark */ 1778852ecd9SLaurent Vivier 1788852ecd9SLaurent Vivierwait_data_mark_byte: 1798852ecd9SLaurent Vivier 1808852ecd9SLaurent Vivier tstb %a2@ 1818852ecd9SLaurent Vivier dbmi %d2, wait_data_mark_byte 1828852ecd9SLaurent Vivier bpl data_exit 1838852ecd9SLaurent Vivier 1848852ecd9SLaurent Vivier moveb %a3@, %d3 1858852ecd9SLaurent Vivier cmpb %a0@+, %d3 1868852ecd9SLaurent Vivier dbne %d1, wait_data_mark_byte 1878852ecd9SLaurent Vivier bne wait_data_init 1888852ecd9SLaurent Vivier 1898852ecd9SLaurent Vivier /* read data */ 1908852ecd9SLaurent Vivier 1918852ecd9SLaurent Vivier tstb %a3@(read_error - read_mark) 1928852ecd9SLaurent Vivier 1938852ecd9SLaurent Vivier movel #sector_size-1, %d4 /* sector size */ 1948852ecd9SLaurent Vivierread_new_data: 1958852ecd9SLaurent Vivier movew #max_retry, %d2 1968852ecd9SLaurent Vivierread_data_loop: 1978852ecd9SLaurent Vivier moveb %a2@, %d5 1988852ecd9SLaurent Vivier andb #0xc0, %d5 1998852ecd9SLaurent Vivier dbne %d2, read_data_loop 2008852ecd9SLaurent Vivier beq data_exit 2018852ecd9SLaurent Vivier moveb %a5@, %a4@+ 2028852ecd9SLaurent Vivier andb #0x40, %d5 2038852ecd9SLaurent Vivier dbne %d4, read_new_data 2048852ecd9SLaurent Vivier beq exit_loop 2058852ecd9SLaurent Vivier moveb %a5@, %a4@+ 2068852ecd9SLaurent Vivier dbra %d4, read_new_data 2078852ecd9SLaurent Vivierexit_loop: 2088852ecd9SLaurent Vivier 2098852ecd9SLaurent Vivier /* read CRC */ 2108852ecd9SLaurent Vivier 2118852ecd9SLaurent Vivier movew #max_retry, %d2 2128852ecd9SLaurent Vivierdata_crc0: 2138852ecd9SLaurent Vivier 2148852ecd9SLaurent Vivier tstb %a2@ 2158852ecd9SLaurent Vivier dbmi %d2, data_crc0 2168852ecd9SLaurent Vivier bpl data_exit 2178852ecd9SLaurent Vivier 2188852ecd9SLaurent Vivier moveb %a3@, %d5 2198852ecd9SLaurent Vivier 2208852ecd9SLaurent Vivier moveq #max_retry, %d2 2218852ecd9SLaurent Vivier 2228852ecd9SLaurent Vivierdata_crc1: 2238852ecd9SLaurent Vivier 2248852ecd9SLaurent Vivier tstb %a2@ 2258852ecd9SLaurent Vivier dbmi %d2, data_crc1 2268852ecd9SLaurent Vivier bpl data_exit 2278852ecd9SLaurent Vivier 2288852ecd9SLaurent Vivier moveb %a3@, %d5 2298852ecd9SLaurent Vivier 2308852ecd9SLaurent Vivier tstb %a3@(read_error - read_mark) 2318852ecd9SLaurent Vivier 2328852ecd9SLaurent Vivier moveb #0x18, %a3@(write_mode0 - read_mark) 2338852ecd9SLaurent Vivier 2348852ecd9SLaurent Vivier /* return number of bytes read */ 2358852ecd9SLaurent Vivier 2368852ecd9SLaurent Vivier movel #sector_size, %d0 2378852ecd9SLaurent Vivier addw #1, %d4 2388852ecd9SLaurent Vivier subl %d4, %d0 2398852ecd9SLaurent Vivier rts 2408852ecd9SLaurent Vivierdata_exit: 2418852ecd9SLaurent Vivier moveb #0x18, %a3@(write_mode0 - read_mark) 2428852ecd9SLaurent Vivier moveq #-1, %d0 2438852ecd9SLaurent Vivier rts 244