linux/drivers/block/swim_asm.S
<<
>>
Prefs
   1/*
   2 * low-level functions for the SWIM floppy controller
   3 *
   4 * needs assembly language because is very timing dependent
   5 * this controller exists only on macintosh 680x0 based
   6 *
   7 * Copyright (C) 2004,2008 Laurent Vivier <Laurent@lvivier.info>
   8 *
   9 * based on Alastair Bridgewater SWIM analysis, 2001
  10 * based on netBSD IWM driver (c) 1997, 1998 Hauke Fath.
  11 *
  12 * This program is free software; you can redistribute it and/or
  13 * modify it under the terms of the GNU General Public License
  14 * as published by the Free Software Foundation; either version
  15 * 2 of the License, or (at your option) any later version.
  16 *
  17 * 2004-08-21 (lv) - Initial implementation
  18 * 2008-11-05 (lv) - add get_swim_mode
  19 */
  20
  21        .equ    write_data,     0x0000
  22        .equ    write_mark,     0x0200
  23        .equ    write_CRC,      0x0400
  24        .equ    write_parameter,0x0600
  25        .equ    write_phase,    0x0800
  26        .equ    write_setup,    0x0a00
  27        .equ    write_mode0,    0x0c00
  28        .equ    write_mode1,    0x0e00
  29        .equ    read_data,      0x1000
  30        .equ    read_mark,      0x1200
  31        .equ    read_error,     0x1400
  32        .equ    read_parameter, 0x1600
  33        .equ    read_phase,     0x1800
  34        .equ    read_setup,     0x1a00
  35        .equ    read_status,    0x1c00
  36        .equ    read_handshake, 0x1e00
  37
  38        .equ    o_side, 0
  39        .equ    o_track, 1
  40        .equ    o_sector, 2
  41        .equ    o_size, 3
  42        .equ    o_crc0, 4
  43        .equ    o_crc1, 5
  44
  45        .equ    seek_time, 30000
  46        .equ    max_retry, 40
  47        .equ    sector_size, 512
  48
  49        .global swim_read_sector_header
  50swim_read_sector_header:
  51        link    %a6, #0
  52        moveml  %d1-%d5/%a0-%a4,%sp@-
  53        movel   %a6@(0x0c), %a4
  54        bsr     mfm_read_addrmark
  55        moveml  %sp@+, %d1-%d5/%a0-%a4
  56        unlk    %a6
  57        rts
  58
  59sector_address_mark:
  60        .byte   0xa1, 0xa1, 0xa1, 0xfe
  61sector_data_mark:
  62        .byte   0xa1, 0xa1, 0xa1, 0xfb
  63
  64mfm_read_addrmark:
  65        movel   %a6@(0x08), %a3
  66        lea     %a3@(read_handshake), %a2
  67        lea     %a3@(read_mark), %a3
  68        moveq   #-1, %d0
  69        movew   #seek_time, %d2
  70
  71wait_header_init:
  72        tstb    %a3@(read_error - read_mark)
  73        moveb   #0x18, %a3@(write_mode0 - read_mark)
  74        moveb   #0x01, %a3@(write_mode1 - read_mark)
  75        moveb   #0x01, %a3@(write_mode0 - read_mark)
  76        tstb    %a3@(read_error - read_mark)
  77        moveb   #0x08, %a3@(write_mode1 - read_mark)
  78
  79        lea     sector_address_mark, %a0
  80        moveq   #3, %d1
  81
  82wait_addr_mark_byte:
  83
  84        tstb    %a2@
  85        dbmi    %d2, wait_addr_mark_byte
  86        bpl     header_exit
  87
  88        moveb   %a3@, %d3
  89        cmpb    %a0@+, %d3
  90        dbne    %d1, wait_addr_mark_byte
  91        bne     wait_header_init
  92
  93        moveq   #max_retry, %d2
  94
  95amark0: tstb    %a2@
  96        dbmi    %d2, amark0
  97        bpl     signal_nonyb
  98
  99        moveb   %a3@, %a4@(o_track)
 100
 101        moveq   #max_retry, %d2
 102
 103amark1: tstb    %a2@
 104        dbmi    %d2, amark1
 105        bpl     signal_nonyb
 106
 107        moveb   %a3@, %a4@(o_side)
 108
 109        moveq   #max_retry, %d2
 110
 111amark2: tstb    %a2@
 112        dbmi    %d2, amark2
 113        bpl     signal_nonyb
 114
 115        moveb   %a3@, %a4@(o_sector)
 116
 117        moveq   #max_retry, %d2
 118
 119amark3: tstb    %a2@
 120        dbmi    %d2, amark3
 121        bpl     signal_nonyb
 122
 123        moveb   %a3@, %a4@(o_size)
 124
 125        moveq   #max_retry, %d2
 126
 127crc0:   tstb    %a2@
 128        dbmi    %d2, crc0
 129        bpl     signal_nonyb
 130
 131        moveb   %a3@, %a4@(o_crc0)
 132
 133        moveq   #max_retry, %d2
 134
 135crc1:   tstb    %a2@
 136        dbmi    %d2, crc1
 137        bpl     signal_nonyb
 138
 139        moveb   %a3@, %a4@(o_crc1)
 140
 141        tstb    %a3@(read_error - read_mark)
 142
 143header_exit:
 144        moveq   #0, %d0
 145        moveb   #0x18, %a3@(write_mode0 - read_mark)
 146        rts
 147signal_nonyb:
 148        moveq   #-1, %d0
 149        moveb   #0x18, %a3@(write_mode0 - read_mark)
 150        rts
 151
 152        .global swim_read_sector_data
 153swim_read_sector_data:
 154        link    %a6, #0
 155        moveml  %d1-%d5/%a0-%a5,%sp@-
 156        movel   %a6@(0x0c), %a4
 157        bsr     mfm_read_data
 158        moveml  %sp@+, %d1-%d5/%a0-%a5
 159        unlk    %a6
 160        rts
 161
 162mfm_read_data:
 163        movel   %a6@(0x08), %a3
 164        lea     %a3@(read_handshake), %a2
 165        lea     %a3@(read_data), %a5
 166        lea     %a3@(read_mark), %a3
 167        movew   #seek_time, %d2
 168
 169wait_data_init:
 170        tstb    %a3@(read_error - read_mark)
 171        moveb   #0x18, %a3@(write_mode0 - read_mark)
 172        moveb   #0x01, %a3@(write_mode1 - read_mark)
 173        moveb   #0x01, %a3@(write_mode0 - read_mark)
 174        tstb    %a3@(read_error - read_mark)
 175        moveb   #0x08, %a3@(write_mode1 - read_mark)
 176
 177        lea     sector_data_mark, %a0
 178        moveq   #3, %d1
 179
 180        /* wait data address mark */
 181
 182wait_data_mark_byte:
 183
 184        tstb    %a2@
 185        dbmi    %d2, wait_data_mark_byte
 186        bpl     data_exit
 187
 188        moveb   %a3@, %d3
 189        cmpb    %a0@+, %d3
 190        dbne    %d1, wait_data_mark_byte
 191        bne     wait_data_init
 192
 193        /* read data */
 194
 195        tstb    %a3@(read_error - read_mark)
 196
 197        movel   #sector_size-1, %d4             /* sector size */
 198read_new_data:
 199        movew   #max_retry, %d2
 200read_data_loop:
 201        moveb   %a2@, %d5
 202        andb    #0xc0, %d5
 203        dbne    %d2, read_data_loop
 204        beq     data_exit
 205        moveb   %a5@, %a4@+
 206        andb    #0x40, %d5
 207        dbne    %d4, read_new_data
 208        beq     exit_loop
 209        moveb   %a5@, %a4@+
 210        dbra    %d4, read_new_data
 211exit_loop:
 212
 213        /* read CRC */
 214
 215        movew   #max_retry, %d2
 216data_crc0:
 217
 218        tstb    %a2@
 219        dbmi    %d2, data_crc0
 220        bpl     data_exit
 221
 222        moveb   %a3@, %d5
 223
 224        moveq   #max_retry, %d2
 225
 226data_crc1:
 227
 228        tstb    %a2@
 229        dbmi    %d2, data_crc1
 230        bpl     data_exit
 231
 232        moveb   %a3@, %d5
 233
 234        tstb    %a3@(read_error - read_mark)
 235
 236        moveb   #0x18, %a3@(write_mode0 - read_mark)
 237
 238        /* return number of bytes read */
 239
 240        movel   #sector_size, %d0
 241        addw    #1, %d4
 242        subl    %d4, %d0
 243        rts
 244data_exit:
 245        moveb   #0x18, %a3@(write_mode0 - read_mark)
 246        moveq   #-1, %d0
 247        rts
 248