|
|       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")