Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / block / swim_asm.S
diff --git a/kernel/drivers/block/swim_asm.S b/kernel/drivers/block/swim_asm.S
new file mode 100644 (file)
index 0000000..c966820
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * 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.
+ *
+ * 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.
+ *
+ * 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