Re: [PATCH 20/31] swim: Check drive ready bit

Laurent Vivier <[email protected]> Sun, 26 Jul 2026 16:48:29 +0200
Newsgroups org.kernel.vger.linux-m68k,org.kernel.vger.linux-block,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Le 16/07/2026 =C3=A0 12:02, Finn Thain a =C3=A9crit=C2=A0:
> The drive provides a readiness signal that has to be tested before
> certain commands are issued to the drive. Rename the SEEK_COMPLETE flag
> as READY because that's how it's known in the documentation as well as
> the mkLinux source code.
>=20
> Poll for that signal after stepping the heads and also after switching
> to MFM mode, as that's what mkLinux does. Check for readiness when
> stepping because testing shows that some drives require this.
>=20
> Fixes: 8852ecd97488 ("m68k: mac - Add SWIM floppy support")
> Signed-off-by: Finn Thain <[email protected]>
> ---
>   drivers/block/swim.c | 29 ++++++++++++++++++++++-------
>   1 file changed, 22 insertions(+), 7 deletions(-)

Reviewed-by: Laurent Vivier <[email protected]>

>=20
> diff --git a/drivers/block/swim.c b/drivers/block/swim.c
> index c10ad1266c3b..77d7ac3765ae 100644
> --- a/drivers/block/swim.c
> +++ b/drivers/block/swim.c
> @@ -117,7 +117,7 @@ struct iwm {
>   #define TACHO		0x1F3
>   #define READ_DATA_1	0x1F4
>   #define GCR_MODE	0x1F5
> -#define SEEK_COMPLETE	0x1F6
> +#define READY		0x1F6
>   #define TWOMEG_MEDIA	0x1F7
>  =20
>   /* Bits in handshake register */
> @@ -316,6 +316,14 @@ static inline bool swim_readbit(struct swim __iomem=
 *base, int bit)
>   #define swim_readbit_timeout_atomic(base, bit, val, timeout_us) \
>   	poll_timeout_us_atomic(, swim_readbit(base, bit) =3D=3D val, 1, timeo=
ut_us, false)
>  =20
> +#define swim_READY_timeout(base) \
> +({ \
> +	int ret =3D swim_readbit_timeout(base, READY, true, 1000 * 1000); \
> +	if (ret) \
> +		printk(KERN_DEBUG "%s: drive not ready\n", __func__); \
> +	ret; \
> +})
> +
>   static inline void swim_drive(struct swim __iomem *base,
>   			      enum drive_location location)
>   {
> @@ -354,8 +362,6 @@ static inline void swim_eject(struct swim __iomem *b=
ase)
>  =20
>   static inline void swim_head(struct swim __iomem *base, enum head head=
)
>   {
> -	/* wait drive is ready */
> -
>   	if (head =3D=3D UPPER_HEAD)
>   		swim_select(base, READ_DATA_1);
>   	else if (head =3D=3D LOWER_HEAD)
> @@ -390,20 +396,25 @@ static inline int swim_track00(struct swim __iomem=
 *base)
>  =20
>   static inline int swim_seek(struct swim __iomem *base, int step)
>   {
> -	if (step =3D=3D 0)
> -		return 0;
> -
>   	if (step < 0) {
>   		swim_action(base, SEEK_NEGATIVE);
>   		step =3D -step;
> -	} else
> +	} else if (step > 0)
>   		swim_action(base, SEEK_POSITIVE);
>  =20
> +	swim_READY_timeout(base);
> +
> +	if (step =3D=3D 0)
> +		return 0;
> +
>   	for ( ; step > 0; step--) {
>   		if (swim_step(base))
>   			return -1;
>   	}
>  =20
> +	msleep(30);
> +	swim_READY_timeout(base);
> +
>   	return 0;
>   }
>  =20
> @@ -485,6 +496,8 @@ static blk_status_t floppy_read_sectors(struct flopp=
y_state *fs,
>  =20
>  =20
>   	swim_drive(base, fs->location);
> +	swim_READY_timeout(base);
> +
>   	for (i =3D req_sector; i < req_sector + sectors_nb; i++) {
>   		int x;
>   		track =3D i / fs->secpercyl;
> @@ -605,6 +618,8 @@ static int floppy_open(struct gendisk *disk, blk_mod=
e_t mode)
>  =20
>   	swim_motor(base, ON);
>   	swim_action(base, SETMFM);
> +	msleep(30);
> +	swim_READY_timeout(base);
>  =20
>   	set_capacity(fs->disk, fs->total_secs);
>  =20