root/sys/arch/x68k/stand/common/chkfmt.s
|
|       check FD format
|
|       Written by ITOH Yasufumi
|       This code is in the public domain
|
| $NetBSD: chkfmt.s,v 1.2 2011/02/21 02:31:58 itohy Exp $

/* FDC address */
#define FDC_STATUS              0xE94001        /* status register */
#define FDC_DATA                0xE94003        /* data register */

#define INT_STAT                0xE9C001        /* interrupt control */
#define INT_FDC_BIT             2

/* Status Register */
#define NE7ST_CB_BIT            4               /* FDC busy */
#define NE7ST_DIO_BIT           6               /* data input/output */
#define NE7ST_RQM_BIT           7               /* request for master */

/* FDC command */
#define NE7CMD_READID           0x4A            /* READ ID */

|
|       Read ID of all sectors in current track.
|       This routine expects that motor on, drive selection
|       and seek is already done.
|
|       input:  d0.b: 0 0 0 0 0 HD US1 US0 (binary)
|       output: d0.l: min # sector (N C H R (2hex))
|               d1.l: max # sector (N C H R (2hex))
|       destroy:
|               d0, d1
|
        .text
        .even
        .globl  check_fd_format
check_fd_format:
        moveml  %d2-%d7/%a1-%a3,%sp@-

        moveb   %d0,%d6                 | head, drive

        lea     FDC_STATUS:l,%a1
        lea     %a1@(FDC_DATA-FDC_STATUS),%a2   | FDC_DATA
        lea     %a2@(INT_STAT-FDC_DATA),%a3     | INT_STAT

        movew   %sr,%sp@-
        oriw    #0x0700,%sr             | keep out interrupts
        moveq   #INT_FDC_BIT,%d5
        bclr    %d5,%a3@                | disable FDC interrupt

        jbsr    read_id_sub
        jne     exit_check_format
        movel   %d3,%d2                 | first sector
        movel   %d3,%d0                 | sector min
sector_is_max:
        movel   %d3,%d1                 | sector max

loop_read_id:
        jbsr    read_id_sub
        jne     exit_check_format
        cmpl    %d0,%d3
        jcc     sector_not_min
        movel   %d3,%d0
sector_not_min:
        cmpl    %d3,%d1
        jcs     sector_is_max
        cmpl    %d2,%d3
        jne     loop_read_id

exit_check_format:
        bset    %d5,%a3@                | enable FDC interrupt
        movew   %a7@+,%sr

        tstl    %d7
        moveml  %a7@+,%d2-%d7/%a1-%a3
        jne     _err_read_id

        rts

|
|       input:  d6.b: 0 0 0 0 0 HD US1 US0 (binary)
|               a1: FDC status addr
|               a2: FDC data addr
|               interrupt must be disabled
|       output: d3.l: sector information: N C H R (2hex)
|               d7.l: status (nonzero if error)
|               Z flag: true if no error, false if error
|       destroy:
|               d3-d4, d7
|
read_id_sub:
        | wait for FDC ready
fdc_wait_ready:
        btst    #NE7ST_CB_BIT,%a1@
        jne     fdc_wait_ready

        | send READ ID command
fdc_send_command1:
        jbsr    fdc_wait_rqm
        jmi     fdc_send_command1
        moveb   #NE7CMD_READID,%a2@

fdc_send_command2:
        jbsr    fdc_wait_rqm
        jmi     fdc_send_command2
        moveb   %d6,%a2@                | X X X X X HD US1 US0 (binary)

        | receive data
        moveq   #2,%d4
        jbsr    fdc_read_bytes
        movel   %d3,%d7                 | d7: FDC status: X ST0 ST1 ST2 (2hex)
        moveq   #3,%d4
        jbsr    fdc_read_bytes          | d3: sector info: C H R N (2hex)
        rorl    #8,%d3                  | d3: sector info: N C H R (2hex)

        andil   #0x00f8ffff,%d7         | check status (must be zero)
        rts

|
|       receive d4:w + 1 bytes from FDC
|
fdc_read_bytes:
        asll    #8,%d3
fdc_read_loop:
        jbsr    fdc_wait_rqm
        jpl     fdc_read_loop
        moveb   %a2@,%d3
        dbra    %d4,fdc_read_bytes
        rts

fdc_wait_rqm:
        moveb   %a1@,%d3
        jpl     fdc_wait_rqm            | NE7ST_RQM_BIT = 7: sign bit
        lslb    #1,%d3                  | NE7ST_DIO_BIT = 6 ... move to bit #7
        rts

|
|       error
|
_err_read_id:
        BOOT_ERROR("READ ID failed")