Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 31 Oct 2018 18:45:26 +0200
From:      Toomas Soome <tsoome@me.com>
To:        src-committers <src-committers@freebsd.org>
Cc:        svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r339959 - head/stand/i386/libi386
Message-ID:  <9C4FF89C-F821-4AE3-BB06-BD23400DA977@me.com>
In-Reply-To: <201810311642.w9VGgexd003377@repo.freebsd.org>
References:  <201810311642.w9VGgexd003377@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
I forgot to note imp, sorry=E2=80=A6

rgds,
toomas

> On 31 Oct 2018, at 18:42, Toomas Soome <tsoome@FreeBSD.org> wrote:
>=20
> Author: tsoome
> Date: Wed Oct 31 16:42:40 2018
> New Revision: 339959
> URL: https://svnweb.freebsd.org/changeset/base/339959
>=20
> Log:
>  loader: issue edd probe before legacy ah=3D08 and detect no media
>=20
>  while probing for drives, use int13 extended info before standard one =
and
>  provide workaround for case we are not getting needed information in =
case
>  of floppy drive.
>=20
>  In case of INT13 errors, there are (at least) 3 error codes appearing =
in case
>  of missin media - 20h, 31h and 80h. Flag the no media and do not =
print an
>  error.
>=20
>  Differential Revision:	https://reviews.freebsd.org/D17667
>=20
> Modified:
>  head/stand/i386/libi386/biosdisk.c
>=20
> Modified: head/stand/i386/libi386/biosdisk.c
> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
> --- head/stand/i386/libi386/biosdisk.c	Wed Oct 31 16:17:45 2018	=
(r339958)
> +++ head/stand/i386/libi386/biosdisk.c	Wed Oct 31 16:42:40 2018	=
(r339959)
> @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
> #include <stand.h>
> #include <machine/bootinfo.h>
> #include <stdarg.h>
> -#include <stdbool.h>
>=20
> #include <bootstrap.h>
> #include <btxv86.h>
> @@ -81,8 +80,10 @@ static struct bdinfo
> #define	BD_MODEINT13	0x0000
> #define	BD_MODEEDD1	0x0001
> #define	BD_MODEEDD3	0x0002
> +#define	BD_MODEEDD	(BD_MODEEDD1 | BD_MODEEDD3)
> #define	BD_MODEMASK	0x0003
> #define	BD_FLOPPY	0x0004
> +#define	BD_NO_MEDIA	0x0008
> 	int		bd_type;	/* BIOS 'drive type' (floppy =
only) */
> 	uint16_t	bd_sectorsize;	/* Sector size */
> 	uint64_t	bd_sectors;	/* Disk size */
> @@ -188,60 +189,83 @@ bd_init(void)
> }
>=20
> /*
> - * Try to detect a device supported by the legacy int13 BIOS
> + * Return EDD version or 0 if EDD is not supported on this drive.
>  */
> static int
> -bd_int13probe(struct bdinfo *bd)
> +bd_check_extensions(int unit)
> {
> -	struct edd_params params;
> -	int ret =3D 1;	/* assume success */
> +	/* Determine if we can use EDD with this device. */
> +	v86.ctl =3D V86_FLAGS;
> +	v86.addr =3D 0x13;
> +	v86.eax =3D 0x4100;
> +	v86.edx =3D unit;
> +	v86.ebx =3D 0x55aa;
> +	v86int();
>=20
> +	if (V86_CY(v86.efl) ||			/* carry set */
> +	    (v86.ebx & 0xffff) !=3D 0xaa55)	/* signature */
> +		return (0);
> +
> +	/* extended disk access functions (AH=3D42h-44h,47h,48h) =
supported */
> +	if ((v86.ecx & EDD_INTERFACE_FIXED_DISK) =3D=3D 0)
> +		return (0);
> +
> +	return ((v86.eax >> 8) & 0xff);
> +}
> +
> +static void
> +bd_reset_disk(int unit)
> +{
> +	/* reset disk */
> 	v86.ctl =3D V86_FLAGS;
> 	v86.addr =3D 0x13;
> +	v86.eax =3D 0;
> +	v86.edx =3D unit;
> +	v86int();
> +}
> +
> +/*
> + * Read CHS info. Return 0 on success, error otherwise.
> + */
> +static int
> +bd_get_diskinfo_std(struct bdinfo *bd)
> +{
> +	bzero(&v86, sizeof(v86));
> +	v86.ctl =3D V86_FLAGS;
> +	v86.addr =3D 0x13;
> 	v86.eax =3D 0x800;
> 	v86.edx =3D bd->bd_unit;
> 	v86int();
>=20
> -	/* Don't error out if we get bad sector number, try EDD as well =
*/
> -	if (V86_CY(v86.efl) ||	/* carry set */
> -	    (v86.edx & 0xff) <=3D (unsigned)(bd->bd_unit & 0x7f))	=
/* unit # bad */
> -		return (0);	/* skip device */
> +	if (V86_CY(v86.efl) && ((v86.eax & 0xff00) !=3D 0))
> +		return ((v86.eax & 0xff00) >> 8);
>=20
> -	if ((v86.ecx & 0x3f) =3D=3D 0)	/* absurd sector number */
> -		ret =3D 0;	/* set error */
> +	/* return custom error on absurd sector number */
> +	if ((v86.ecx & 0x3f) =3D=3D 0)
> +		return (0x60);
>=20
> -	/* Convert max cyl # -> # of cylinders */
> 	bd->bd_cyl =3D ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> =
8) + 1;
> 	/* Convert max head # -> # of heads */
> 	bd->bd_hds =3D ((v86.edx & 0xff00) >> 8) + 1;
> 	bd->bd_sec =3D v86.ecx & 0x3f;
> -	bd->bd_type =3D v86.ebx & 0xff;
> -	bd->bd_flags |=3D BD_MODEINT13;
> +	bd->bd_type =3D v86.ebx;
> +	bd->bd_sectors =3D (uint64_t)bd->bd_cyl * bd->bd_hds * =
bd->bd_sec;
>=20
> -	/* Calculate sectors count from the geometry */
> -	bd->bd_sectors =3D bd->bd_cyl * bd->bd_hds * bd->bd_sec;
> -	bd->bd_sectorsize =3D BIOSDISK_SECSIZE;
> -	DEBUG("unit 0x%x geometry %d/%d/%d", bd->bd_unit, bd->bd_cyl,
> -	    bd->bd_hds, bd->bd_sec);
> +	return (0);
> +}
>=20
> -	/* Determine if we can use EDD with this device. */
> -	v86.ctl =3D V86_FLAGS;
> -	v86.addr =3D 0x13;
> -	v86.eax =3D 0x4100;
> -	v86.edx =3D bd->bd_unit;
> -	v86.ebx =3D 0x55aa;
> -	v86int();
> -	if (V86_CY(v86.efl) ||	/* carry set */
> -	    (v86.ebx & 0xffff) !=3D 0xaa55 || /* signature */
> -	    (v86.ecx & EDD_INTERFACE_FIXED_DISK) =3D=3D 0)
> -		return (ret);	/* return code from int13 AH=3D08 */
> +/*
> + * Read EDD info. Return 0 on success, error otherwise.
> + */
> +static int
> +bd_get_diskinfo_ext(struct bdinfo *bd)
> +{
> +	struct edd_params params;
> +	uint64_t total;
>=20
> -	/* EDD supported */
> -	bd->bd_flags |=3D BD_MODEEDD1;
> -	if ((v86.eax & 0xff00) >=3D 0x3000)
> -		bd->bd_flags |=3D BD_MODEEDD3;
> 	/* Get disk params */
> -	params.len =3D sizeof(struct edd_params);
> +	bzero(&params, sizeof(params));
> +	params.len =3D sizeof(params);
> 	v86.ctl =3D V86_FLAGS;
> 	v86.addr =3D 0x13;
> 	v86.eax =3D 0x4800;
> @@ -249,37 +273,120 @@ bd_int13probe(struct bdinfo *bd)
> 	v86.ds =3D VTOPSEG(&params);
> 	v86.esi =3D VTOPOFF(&params);
> 	v86int();
> -	if (!V86_CY(v86.efl)) {
> -		uint64_t total;
>=20
> -		/*
> -		 * Sector size must be a multiple of 512 bytes.
> -		 * An alternate test would be to check power of 2,
> -		 * powerof2(params.sector_size).
> -		 * 4K is largest read buffer we can use at this time.
> -		 */
> -		if (params.sector_size >=3D 512 &&
> -		    params.sector_size <=3D 4096 &&
> -		    (params.sector_size % BIOSDISK_SECSIZE) =3D=3D 0)
> -			bd->bd_sectorsize =3D params.sector_size;
> +	if (V86_CY(v86.efl) && ((v86.eax & 0xff00) !=3D 0))
> +		return ((v86.eax & 0xff00) >> 8);
>=20
> -		total =3D bd->bd_sectorsize * params.sectors;
> -		if (params.sectors !=3D 0) {
> -			/* Only update if we did not overflow. */
> -			if (total > params.sectors)
> -				bd->bd_sectors =3D params.sectors;
> -		}
> +	/*
> +	 * Sector size must be a multiple of 512 bytes.
> +	 * An alternate test would be to check power of 2,
> +	 * powerof2(params.sector_size).
> +	 * 4K is largest read buffer we can use at this time.
> +	 */
> +	if (params.sector_size >=3D 512 &&
> +	    params.sector_size <=3D 4096 &&
> +	    (params.sector_size % BIOSDISK_SECSIZE) =3D=3D 0)
> +		bd->bd_sectorsize =3D params.sector_size;
>=20
> +	bd->bd_cyl =3D params.cylinders;
> +	bd->bd_hds =3D params.heads;
> +	bd->bd_sec =3D params.sectors_per_track;
> +
> +	if (params.sectors !=3D 0) {
> +		total =3D params.sectors;
> +	} else {
> 		total =3D (uint64_t)params.cylinders *
> 		    params.heads * params.sectors_per_track;
> -		if (total > 0 && bd->bd_sectors > total)
> -			bd->bd_sectors =3D total;
> +	}
> +	bd->bd_sectors =3D total;
>=20
> -		ret =3D 1;
> +	return (0);
> +}
> +
> +/*
> + * Try to detect a device supported by the legacy int13 BIOS
> + */
> +static int
> +bd_int13probe(struct bdinfo *bd)
> +{
> +	int edd;
> +	int ret;
> +
> +	bd->bd_flags &=3D ~BD_NO_MEDIA;
> +
> +	edd =3D bd_check_extensions(bd->bd_unit);
> +	if (edd =3D=3D 0)
> +		bd->bd_flags |=3D BD_MODEINT13;
> +	else if (edd < 0x30)
> +		bd->bd_flags |=3D BD_MODEEDD1;
> +	else
> +		bd->bd_flags |=3D BD_MODEEDD3;
> +
> +	/* Default sector size */
> +	bd->bd_sectorsize =3D BIOSDISK_SECSIZE;
> +
> +	/*
> +	 * Test if the floppy device is present, so we can avoid =
receiving
> +	 * bogus information from bd_get_diskinfo_std().
> +	 */
> +	if (bd->bd_unit < 0x80) {
> +		/* reset disk */
> +		bd_reset_disk(bd->bd_unit);
> +
> +		/* Get disk type */
> +		v86.ctl =3D V86_FLAGS;
> +		v86.addr =3D 0x13;
> +		v86.eax =3D 0x1500;
> +		v86.edx =3D bd->bd_unit;
> +		v86int();
> +		if (V86_CY(v86.efl) || (v86.eax & 0x300) =3D=3D 0)
> +			return (0);
> 	}
> -	DEBUG("unit 0x%x flags %x, sectors %llu, sectorsize %u",
> -	    bd->bd_unit, bd->bd_flags, bd->bd_sectors, =
bd->bd_sectorsize);
> -	return (ret);
> +
> +	ret =3D 1;
> +	if (edd !=3D 0)
> +		ret =3D bd_get_diskinfo_ext(bd);
> +	if (ret !=3D 0 || bd->bd_sectors =3D=3D 0)
> +		ret =3D bd_get_diskinfo_std(bd);
> +
> +	if (ret !=3D 0 && bd->bd_unit < 0x80) {
> +		/* Set defaults for 1.44 floppy */
> +		bd->bd_cyl =3D 80;
> +		bd->bd_hds =3D 2;
> +		bd->bd_sec =3D 18;
> +		bd->bd_type =3D 4;
> +		bd->bd_sectors =3D 2880;
> +		/* Since we are there, there most likely is no media */
> +		bd->bd_flags |=3D BD_NO_MEDIA;
> +		ret =3D 0;
> +	}
> +
> +	if (ret !=3D 0) {
> +		if (bd->bd_sectors !=3D 0 && edd !=3D 0) {
> +			bd->bd_sec =3D 63;
> +			bd->bd_hds =3D 255;
> +			bd->bd_cyl =3D
> +			    (bd->bd_sectors + bd->bd_sec * bd->bd_hds - =
1) /
> +			    bd->bd_sec * bd->bd_hds;
> +		} else {
> +			printf("Can not get information about %s unit =
%#x\n",
> +			    biosdisk.dv_name, bd->bd_unit);
> +			return (0);
> +		}
> +	}
> +
> +	if (bd->bd_sec =3D=3D 0)
> +		bd->bd_sec =3D 63;
> +	if (bd->bd_hds =3D=3D 0)
> +		bd->bd_hds =3D 255;
> +
> +	if (bd->bd_sectors =3D=3D 0)
> +		bd->bd_sectors =3D (uint64_t)bd->bd_cyl * bd->bd_hds * =
bd->bd_sec;
> +
> +	DEBUG("unit 0x%x geometry %d/%d/%d", bd->bd_unit, bd->bd_cyl,
> +	    bd->bd_hds, bd->bd_sec);
> +
> +	return (1);
> }
>=20
> /*
> @@ -301,9 +408,11 @@ bd_print(int verbose)
>=20
> 	for (i =3D 0; i < nbdinfo; i++) {
> 		snprintf(line, sizeof(line),
> -		    "    disk%d:   BIOS drive %c (%ju X %u):\n", i,
> +		    "    disk%d:   BIOS drive %c (%s%ju X %u):\n", i,
> 		    (bdinfo[i].bd_unit < 0x80) ? ('A' + =
bdinfo[i].bd_unit):
> 		    ('C' + bdinfo[i].bd_unit - 0x80),
> +		    (bdinfo[i].bd_flags & BD_NO_MEDIA) =3D=3D =
BD_NO_MEDIA ?
> +		    "no media, " : "",
> 		    (uintmax_t)bdinfo[i].bd_sectors,
> 		    bdinfo[i].bd_sectorsize);
> 		if ((ret =3D pager_output(line)) !=3D 0)
> @@ -351,6 +460,11 @@ bd_open(struct open_file *f, ...)
>=20
> 	if (dev->dd.d_unit < 0 || dev->dd.d_unit >=3D nbdinfo)
> 		return (EIO);
> +
> +	if ((BD(dev).bd_flags & BD_NO_MEDIA) =3D=3D BD_NO_MEDIA) {
> +		if (!bd_int13probe(&BD(dev)))
> +			return (EIO);
> +	}
> 	BD(dev).bd_open++;
> 	if (BD(dev).bd_bcache =3D=3D NULL)
> 	    BD(dev).bd_bcache =3D bcache_allocate();
> @@ -499,7 +613,7 @@ bd_realstrategy(void *devdata, int rw, daddr_t =
dblk, s
> 	 * partition.
> 	 */
> 	if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) =3D=3D 0) {
> -		/* DIOCGMEDIASIZE returns bytes. */
> +		/* DIOCGMEDIASIZE does return bytes. */
> 		disk_blocks /=3D BD(dev).bd_sectorsize;
> 	} else {
> 		/* We should not get here. Just try to survive. */
> @@ -685,29 +799,33 @@ bd_io(struct disk_devdesc *dev, daddr_t dblk, =
int blks
> 	if (dowrite =3D=3D BD_RD && dblk >=3D 0x100000000)
> 		bd_io_workaround(dev);
> 	for (retry =3D 0; retry < 3; retry++) {
> -		/* if retrying, reset the drive */
> -		if (retry > 0) {
> -			v86.ctl =3D V86_FLAGS;
> -			v86.addr =3D 0x13;
> -			v86.eax =3D 0;
> -			v86.edx =3D BD(dev).bd_unit;
> -			v86int();
> -		}
> -
> -		if (BD(dev).bd_flags & BD_MODEEDD1)
> +		if (BD(dev).bd_flags & BD_MODEEDD)
> 			result =3D bd_edd_io(dev, dblk, blks, dest, =
dowrite);
> 		else
> 			result =3D bd_chs_io(dev, dblk, blks, dest, =
dowrite);
>=20
> -		if (result =3D=3D 0)
> +		if (result =3D=3D 0) {
> +			if (BD(dev).bd_flags & BD_NO_MEDIA)
> +				BD(dev).bd_flags &=3D ~BD_NO_MEDIA;
> 			break;
> +		}
> +
> +		bd_reset_disk(BD(dev).bd_unit);
> +
> +		/*
> +		 * Error codes:
> +		 * 20h	controller failure
> +		 * 31h	no media in drive (IBM/MS INT 13 extensions)
> +		 * 80h	no media in drive, VMWare (Fusion)
> +		 * There is no reason to repeat the IO with errors =
above.
> +		 */
> +		if (result =3D=3D 0x20 || result =3D=3D 0x31 || result =
=3D=3D 0x80) {
> +			BD(dev).bd_flags |=3D BD_NO_MEDIA;
> +			break;
> +		}
> 	}
>=20
> -	/*
> -	 * 0x20 - Controller failure. This is common error when the
> -	 * media is not present.
> -	 */
> -	if (result !=3D 0 && result !=3D 0x20) {
> +	if (result !=3D 0 && (BD(dev).bd_flags & BD_NO_MEDIA) =3D=3D 0) =
{
> 		if (dowrite =3D=3D BD_WR) {
> 			printf("%s%d: Write %d sector(s) from %p (0x%x) =
"
> 			    "to %lld: 0x%x\n", dev->dd.d_dev->dv_name,
>=20




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9C4FF89C-F821-4AE3-BB06-BD23400DA977>