mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
![Thomas Gleixner](/assets/img/avatar_default.png)
Based on 1 normalized pattern(s): this program is free software you can redistribute it and or modify it under the terms of the gnu general public license as published by the free software foundation either version 2 of the license or at your option any later version extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 3029 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070032.746973796@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
243 lines
4.4 KiB
ArmAsm
243 lines
4.4 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* low-level functions for the SWIM floppy controller
|
|
*
|
|
* needs assembly language because is very timing dependent
|
|
* this controller exists only on macintosh 680x0 based
|
|
*
|
|
* Copyright (C) 2004,2008 Laurent Vivier <Laurent@lvivier.info>
|
|
*
|
|
* based on Alastair Bridgewater SWIM analysis, 2001
|
|
* based on netBSD IWM driver (c) 1997, 1998 Hauke Fath.
|
|
*
|
|
* 2004-08-21 (lv) - Initial implementation
|
|
* 2008-11-05 (lv) - add get_swim_mode
|
|
*/
|
|
|
|
.equ write_data, 0x0000
|
|
.equ write_mark, 0x0200
|
|
.equ write_CRC, 0x0400
|
|
.equ write_parameter,0x0600
|
|
.equ write_phase, 0x0800
|
|
.equ write_setup, 0x0a00
|
|
.equ write_mode0, 0x0c00
|
|
.equ write_mode1, 0x0e00
|
|
.equ read_data, 0x1000
|
|
.equ read_mark, 0x1200
|
|
.equ read_error, 0x1400
|
|
.equ read_parameter, 0x1600
|
|
.equ read_phase, 0x1800
|
|
.equ read_setup, 0x1a00
|
|
.equ read_status, 0x1c00
|
|
.equ read_handshake, 0x1e00
|
|
|
|
.equ o_side, 0
|
|
.equ o_track, 1
|
|
.equ o_sector, 2
|
|
.equ o_size, 3
|
|
.equ o_crc0, 4
|
|
.equ o_crc1, 5
|
|
|
|
.equ seek_time, 30000
|
|
.equ max_retry, 40
|
|
.equ sector_size, 512
|
|
|
|
.global swim_read_sector_header
|
|
swim_read_sector_header:
|
|
link %a6, #0
|
|
moveml %d1-%d5/%a0-%a4,%sp@-
|
|
movel %a6@(0x0c), %a4
|
|
bsr mfm_read_addrmark
|
|
moveml %sp@+, %d1-%d5/%a0-%a4
|
|
unlk %a6
|
|
rts
|
|
|
|
sector_address_mark:
|
|
.byte 0xa1, 0xa1, 0xa1, 0xfe
|
|
sector_data_mark:
|
|
.byte 0xa1, 0xa1, 0xa1, 0xfb
|
|
|
|
mfm_read_addrmark:
|
|
movel %a6@(0x08), %a3
|
|
lea %a3@(read_handshake), %a2
|
|
lea %a3@(read_mark), %a3
|
|
moveq #-1, %d0
|
|
movew #seek_time, %d2
|
|
|
|
wait_header_init:
|
|
tstb %a3@(read_error - read_mark)
|
|
moveb #0x18, %a3@(write_mode0 - read_mark)
|
|
moveb #0x01, %a3@(write_mode1 - read_mark)
|
|
moveb #0x01, %a3@(write_mode0 - read_mark)
|
|
tstb %a3@(read_error - read_mark)
|
|
moveb #0x08, %a3@(write_mode1 - read_mark)
|
|
|
|
lea sector_address_mark, %a0
|
|
moveq #3, %d1
|
|
|
|
wait_addr_mark_byte:
|
|
|
|
tstb %a2@
|
|
dbmi %d2, wait_addr_mark_byte
|
|
bpl header_exit
|
|
|
|
moveb %a3@, %d3
|
|
cmpb %a0@+, %d3
|
|
dbne %d1, wait_addr_mark_byte
|
|
bne wait_header_init
|
|
|
|
moveq #max_retry, %d2
|
|
|
|
amark0: tstb %a2@
|
|
dbmi %d2, amark0
|
|
bpl signal_nonyb
|
|
|
|
moveb %a3@, %a4@(o_track)
|
|
|
|
moveq #max_retry, %d2
|
|
|
|
amark1: tstb %a2@
|
|
dbmi %d2, amark1
|
|
bpl signal_nonyb
|
|
|
|
moveb %a3@, %a4@(o_side)
|
|
|
|
moveq #max_retry, %d2
|
|
|
|
amark2: tstb %a2@
|
|
dbmi %d2, amark2
|
|
bpl signal_nonyb
|
|
|
|
moveb %a3@, %a4@(o_sector)
|
|
|
|
moveq #max_retry, %d2
|
|
|
|
amark3: tstb %a2@
|
|
dbmi %d2, amark3
|
|
bpl signal_nonyb
|
|
|
|
moveb %a3@, %a4@(o_size)
|
|
|
|
moveq #max_retry, %d2
|
|
|
|
crc0: tstb %a2@
|
|
dbmi %d2, crc0
|
|
bpl signal_nonyb
|
|
|
|
moveb %a3@, %a4@(o_crc0)
|
|
|
|
moveq #max_retry, %d2
|
|
|
|
crc1: tstb %a2@
|
|
dbmi %d2, crc1
|
|
bpl signal_nonyb
|
|
|
|
moveb %a3@, %a4@(o_crc1)
|
|
|
|
tstb %a3@(read_error - read_mark)
|
|
|
|
header_exit:
|
|
moveq #0, %d0
|
|
moveb #0x18, %a3@(write_mode0 - read_mark)
|
|
rts
|
|
signal_nonyb:
|
|
moveq #-1, %d0
|
|
moveb #0x18, %a3@(write_mode0 - read_mark)
|
|
rts
|
|
|
|
.global swim_read_sector_data
|
|
swim_read_sector_data:
|
|
link %a6, #0
|
|
moveml %d1-%d5/%a0-%a5,%sp@-
|
|
movel %a6@(0x0c), %a4
|
|
bsr mfm_read_data
|
|
moveml %sp@+, %d1-%d5/%a0-%a5
|
|
unlk %a6
|
|
rts
|
|
|
|
mfm_read_data:
|
|
movel %a6@(0x08), %a3
|
|
lea %a3@(read_handshake), %a2
|
|
lea %a3@(read_data), %a5
|
|
lea %a3@(read_mark), %a3
|
|
movew #seek_time, %d2
|
|
|
|
wait_data_init:
|
|
tstb %a3@(read_error - read_mark)
|
|
moveb #0x18, %a3@(write_mode0 - read_mark)
|
|
moveb #0x01, %a3@(write_mode1 - read_mark)
|
|
moveb #0x01, %a3@(write_mode0 - read_mark)
|
|
tstb %a3@(read_error - read_mark)
|
|
moveb #0x08, %a3@(write_mode1 - read_mark)
|
|
|
|
lea sector_data_mark, %a0
|
|
moveq #3, %d1
|
|
|
|
/* wait data address mark */
|
|
|
|
wait_data_mark_byte:
|
|
|
|
tstb %a2@
|
|
dbmi %d2, wait_data_mark_byte
|
|
bpl data_exit
|
|
|
|
moveb %a3@, %d3
|
|
cmpb %a0@+, %d3
|
|
dbne %d1, wait_data_mark_byte
|
|
bne wait_data_init
|
|
|
|
/* read data */
|
|
|
|
tstb %a3@(read_error - read_mark)
|
|
|
|
movel #sector_size-1, %d4 /* sector size */
|
|
read_new_data:
|
|
movew #max_retry, %d2
|
|
read_data_loop:
|
|
moveb %a2@, %d5
|
|
andb #0xc0, %d5
|
|
dbne %d2, read_data_loop
|
|
beq data_exit
|
|
moveb %a5@, %a4@+
|
|
andb #0x40, %d5
|
|
dbne %d4, read_new_data
|
|
beq exit_loop
|
|
moveb %a5@, %a4@+
|
|
dbra %d4, read_new_data
|
|
exit_loop:
|
|
|
|
/* read CRC */
|
|
|
|
movew #max_retry, %d2
|
|
data_crc0:
|
|
|
|
tstb %a2@
|
|
dbmi %d2, data_crc0
|
|
bpl data_exit
|
|
|
|
moveb %a3@, %d5
|
|
|
|
moveq #max_retry, %d2
|
|
|
|
data_crc1:
|
|
|
|
tstb %a2@
|
|
dbmi %d2, data_crc1
|
|
bpl data_exit
|
|
|
|
moveb %a3@, %d5
|
|
|
|
tstb %a3@(read_error - read_mark)
|
|
|
|
moveb #0x18, %a3@(write_mode0 - read_mark)
|
|
|
|
/* return number of bytes read */
|
|
|
|
movel #sector_size, %d0
|
|
addw #1, %d4
|
|
subl %d4, %d0
|
|
rts
|
|
data_exit:
|
|
moveb #0x18, %a3@(write_mode0 - read_mark)
|
|
moveq #-1, %d0
|
|
rts
|