Hello everyone,

when trying to use the fdrawcmd format_n_write command it gives an IO error and does not write the data. Reading the FDC data sheet did not reveal any hints either.

Attached is a sample script that shows how I use the format_n_write command. When the variable format_n_write is set to 0 the script also uses the more common way of formatting and then writing a track, which works without problems.

Does anyone have a clue what I may be missing, or maybe the FDC is buggy? Reading the source code of fdrawcmd it appears that the ioctl call for the FDRAWCMD fails with errno EIO. The floppy module then stops working and needs to be reloaded. The kernel output at that point is:

[19580.077949] floppy driver state
[19580.077983] -------------------
[19580.078102] now=4819734 last interrupt=4818815 diff=919 last called handler=main_command_interrupt [floppy]
[19580.078147] timeout_message=floppy start
[19580.078181] last output bytes:
[19580.078226]  8 80 4818474
[19580.078269]  8 80 4818474
[19580.078313]  f 80 4818815
[19580.078356]  0 90 4818815
[19580.078398]  0 90 4818815
[19580.078440]  8 81 4818815
[19580.078483] 13 80 4818982
[19580.078525]  0 90 4818982
[19580.078568] 1a 90 4818982
[19580.078610]  0 90 4818982
[19580.078652] 8e 80 4818982
[19580.078695]  3 80 4818982
[19580.078738] c1 90 4818982
[19580.078779]  a 90 4818982
[19580.078822] ef 80 4818982
[19580.078864]  0 90 4818982
[19580.078906]  2 90 4818982
[19580.078949]  9 81 4818982
[19580.078991] 50 91 4818982
[19580.079033]  0 91 4818982
[19580.079069] last result at 4818982
[19580.079106] last redo_fd_request at 4818815
[19580.079160] 00 00 00 00 c1 0a 09 04 1a 00 ..........
[19580.079209] status=91
[19580.079243] fdc_busy=1
[19580.079312] do_floppy=main_command_interrupt [floppy]
[19580.079356] cont=c6bbfda4
[19580.079393] current_req=  (null)
[19580.079430] command_status=-1

[19580.079514] floppy0: floppy timeout called

Best regards,

Stefan Fiedler



#!/bin/bash

drive_nr=0
drive_type="DD"
drive_side="DS"
drive_geom="5 1/4"
drive=/dev/fd$drive_nr

format_n_write=1

case $drive_type in
"HD") rate=0 # for HD
    track_step=1
    track_max=80
    read_id_count=32
    ;;
"DD")
    track_step=2
    track_max=40
    read_id_count=18

    case "$drive_geom" in
    "5 1/4") rate=1 ;; # for DD 5 1/4"
    "3 1/2") rate=2 ;; # for DD 3 1/2"
    esac
    ;;
esac

case $drive_geom in
"5 1/4") gpl1=0x2a ; gpl2=0x50 ;;
"3 1/2") gpl1=0x1b ; gpl2=0x54 ;;
esac
if [ "$drive_type" = "ED" ] ; then gpl1=0x38 ; gpl2=0x53 ; fi

szgap=0x1b # default for 3,5" drives with 512 bytes/sector? Unused by FDC?


track=0
drvsel=0

echo fdrawcmd drive=$drive rate=$rate seek $drvsel $(( $track * $track_step ))
fdrawcmd drive=$drive rate=$rate seek $drvsel $(( $track * $track_step )) 2>rawcmd_stderr >rawcmd_stdout
           
nr_sectors=9
           
           
szcod=2
for (( x=1; $x <= $(( 2 ** ($szcod + 4) )); x=$(( $x + 1 )) )) ; do
    printf "\x01\x23\x45\x67\x89\xab\xcd\xef"
done > tmp_sector.data

for (( x=1; $x <= $nr_sectors; x=$(( $x + 1 )) )) ; do
    C=$(( $track * $track_step ))
    H=0
    R=$x
    Z=$szcod

    printf "\x${C#0x}\x${H#0x}\x${R#0x}\x${Z#0x}"
done > tmp_id.data

length=$(( 2**($szcod+7) * $nr_sectors + 4 * 9 ))

spt=$nr_sectors
gpl3=$gpl2
fmtfill=0x0

if [ "$format_n_write" = 0 ] ; then
    echo fdrawcmd drive=$drive rate=$rate format $drvsel $szcod $spt $gpl3 $fmtfill
    fdrawcmd drive=$drive rate=$rate format $drvsel $szcod $spt $gpl3 $fmtfill < tmp_id.data

    length=$(( 2**($Z+7) * $nr_sectors ))

    C=$(( $track * $track_step ))
    H=0
    R=1
    Z=$szcod

    for (( x=1; $x <= $nr_sectors; x=$(( $x + 1 )) )) ; do
        cat "tmp_sector.data"
    done > tmp_track2.data

    szcod2=0xff

    echo fdrawcmd drive=$drive rate=$rate length=$length write $drvsel $C $H $R $Z $spt $szgap $szcod2
    fdrawcmd drive=$drive rate=$rate length=$length write $drvsel $C $H $R $Z $spt $szgap $szcod2 < tmp_track2.data
else

    for (( x=1; $x <= $nr_sectors; x=$(( $x + 1 )) )) ; do
        C=$(( $track * $track_step ))
        H=0
        R=$x
        Z=$szcod

        printf "\x${C#0x}\x${H#0x}\x${R#0x}\x${Z#0x}"
        cat "tmp_sector.data"
    done > tmp_track.data

    length=$(( 2**($Z+7) * $nr_sectors ))

    echo fdrawcmd drive=$drive rate=$rate length=$length format_n_write $drvsel $szcod $spt $gpl3 $fmtfill
    strace fdrawcmd drive=$drive rate=$rate length=$length format_n_write $drvsel $szcod $spt $gpl3 $fmtfill < tmp_track.data
fi

szcod2=0xff

echo fdrawcmd drive=$drive rate=$rate length=$length read $drvsel $C $H $R $Z $spt $szgap $szcod2
fdrawcmd drive=$drive rate=$rate length=$length read $drvsel $C $H $R $Z $spt $szgap $szcod2 > tmp_track3.data