123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- /*
- * 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
|