From owner-svn-src-all@freebsd.org Wed Oct 31 16:45:46 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 74CB410DEC1C; Wed, 31 Oct 2018 16:45:46 +0000 (UTC) (envelope-from tsoome@me.com) Received: from mr28p00im-ztfo03025201.me.com (mr28p00im-ztfo03025201.me.com [17.110.71.102]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 15CF77DB6B; Wed, 31 Oct 2018 16:45:46 +0000 (UTC) (envelope-from tsoome@me.com) Received: from process-dkim-sign-daemon.mr28p00im-ztfo03025201.me.com by mr28p00im-ztfo03025201.me.com (Oracle Communications Messaging Server 8.0.2.2.20180531 64bit (built May 31 2018)) id <0PHH00E000I3VW00@mr28p00im-ztfo03025201.me.com>; Wed, 31 Oct 2018 16:45:35 +0000 (GMT) Received: from icloud.com ([127.0.0.1]) by mr28p00im-ztfo03025201.me.com (Oracle Communications Messaging Server 8.0.2.2.20180531 64bit (built May 31 2018)) with ESMTPSA id <0PHH00I3J2JR2L10@mr28p00im-ztfo03025201.me.com>; Wed, 31 Oct 2018 16:45:32 +0000 (GMT) X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1807170000 definitions=main-1810310139 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-10-31_06:,, signatures=0 Content-type: text/plain; charset=utf-8 MIME-version: 1.0 (Mac OS X Mail 12.0 \(3445.100.39\)) Subject: Re: svn commit: r339959 - head/stand/i386/libi386 From: Toomas Soome In-reply-to: <201810311642.w9VGgexd003377@repo.freebsd.org> Date: Wed, 31 Oct 2018 18:45:26 +0200 Cc: svn-src-all@freebsd.org, svn-src-head@freebsd.org Content-transfer-encoding: quoted-printable Message-id: <9C4FF89C-F821-4AE3-BB06-BD23400DA977@me.com> References: <201810311642.w9VGgexd003377@repo.freebsd.org> To: src-committers X-Mailer: Apple Mail (2.3445.100.39) X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 31 Oct 2018 16:45:46 -0000 I forgot to note imp, sorry=E2=80=A6 rgds, toomas > On 31 Oct 2018, at 18:42, Toomas Soome 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 > #include > #include > -#include >=20 > #include > #include > @@ -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(¶ms, 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(¶ms); > v86.esi =3D VTOPOFF(¶ms); > 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