Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Apr 2019 03:36:06 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r346476 - in stable/11/stand: common i386/libfirewire i386/libi386 i386/loader libsa uboot/lib
Message-ID:  <201904210336.x3L3a634020498@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Sun Apr 21 03:36:05 2019
New Revision: 346476
URL: https://svnweb.freebsd.org/changeset/base/346476

Log:
  MFC r341253, r341328, r342619, r342626, r342707, r342785, r342865
  
  r341253:
  The libstand's panic() appends its own '\n' to the message, so that users of the API
  don't need to supply one.
  
  r341328:
  loader: create separate lists for fd, cd and hd, merge bioscd with biosdisk
  
  Create unified block IO implementation in BIOS version, like it is done in UEFI
  side. Implement fd, disk and cd device lists, this will split floppy devices
  from disks and will allow us to have consistent, predictable device naming
  (modulo BIOS issues).
  
  r342619:
  loader: create bio_alloc and bio_free for bios bounce buffer
  
  We do have 16KB buffer space defined in pxe.c, move it to bio.c and implement
  bio_alloc()/bio_free() interface to make it possible to use this space for
  other BIOS calls (notably, from biosdisk.c).
  
  r342626:
  Add Copyright.
  
  r342707:
  i386_parsedev() needs to support fd devices
  
  r342785:
  With buggy int13 ah=15, we can mis-identify the floppy devices.
  
  We have no option than trust INT13 ah=08 return code during the init phase.
  
  r342865:
  biospci_write_config args were backwards
  
  biospci_write_config args swapped length and value to write. Some
  hardware coped just fine, while other hardware had issues.
  
  PR: 155441, 234460

Added:
  stable/11/stand/i386/libi386/bio.c
     - copied, changed from r342619, head/stand/i386/libi386/bio.c
Deleted:
  stable/11/stand/i386/libi386/bioscd.c
Modified:
  stable/11/stand/common/interp_forth.c
  stable/11/stand/i386/libfirewire/firewire.c
  stable/11/stand/i386/libi386/Makefile
  stable/11/stand/i386/libi386/biosdisk.c
  stable/11/stand/i386/libi386/bootinfo32.c
  stable/11/stand/i386/libi386/devicename.c
  stable/11/stand/i386/libi386/libi386.h
  stable/11/stand/i386/libi386/pxe.c
  stable/11/stand/i386/loader/chain.c
  stable/11/stand/i386/loader/conf.c
  stable/11/stand/i386/loader/main.c
  stable/11/stand/libsa/arp.c
  stable/11/stand/libsa/assert.c
  stable/11/stand/libsa/bzipfs.c
  stable/11/stand/libsa/netif.c
  stable/11/stand/libsa/sbrk.c
  stable/11/stand/uboot/lib/copy.c
  stable/11/stand/uboot/lib/net.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/stand/common/interp_forth.c
==============================================================================
--- stable/11/stand/common/interp_forth.c	Sun Apr 21 03:30:47 2019	(r346475)
+++ stable/11/stand/common/interp_forth.c	Sun Apr 21 03:36:05 2019	(r346476)
@@ -144,7 +144,7 @@ bf_command(FICL_VM *vm)
 		printf("%s\n", command_errmsg);
 		break;
 	case CMD_FATAL:
-		panic("%s\n", command_errmsg);
+		panic("%s", command_errmsg);
 	}
 
 	free(line);

Modified: stable/11/stand/i386/libfirewire/firewire.c
==============================================================================
--- stable/11/stand/i386/libfirewire/firewire.c	Sun Apr 21 03:30:47 2019	(r346475)
+++ stable/11/stand/i386/libfirewire/firewire.c	Sun Apr 21 03:36:05 2019	(r346476)
@@ -107,9 +107,9 @@ fw_probe(int index, struct fwohci_softc *sc)
 	}
 
 	biospci_write_config(sc->locator,
-		0x4	/* command */,
-		0x6	/* enable bus master and memory mapped I/O */,
-		BIOSPCI_16BITS);
+	    0x4	/* command */,
+	    BIOSPCI_16BITS,
+	    0x6	/* enable bus master and memory mapped I/O */);
 
 	biospci_read_config(sc->locator, 0x00 /*devid*/, BIOSPCI_32BITS,
 		&sc->devid);

Modified: stable/11/stand/i386/libi386/Makefile
==============================================================================
--- stable/11/stand/i386/libi386/Makefile	Sun Apr 21 03:30:47 2019	(r346475)
+++ stable/11/stand/i386/libi386/Makefile	Sun Apr 21 03:36:05 2019	(r346476)
@@ -4,7 +4,7 @@
 
 LIB=			i386
 
-SRCS=	biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \
+SRCS=	bio.c biosacpi.c biosdisk.c biosmem.c biospnp.c \
 	biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \
 	comconsole.c devicename.c elf32_freebsd.c \
 	elf64_freebsd.c multiboot.c multiboot_tramp.S relocater_tramp.S \

Copied and modified: stable/11/stand/i386/libi386/bio.c (from r342619, head/stand/i386/libi386/bio.c)
==============================================================================
--- head/stand/i386/libi386/bio.c	Sun Dec 30 09:35:47 2018	(r342619, copy source)
+++ stable/11/stand/i386/libi386/bio.c	Sun Apr 21 03:36:05 2019	(r346476)
@@ -1,4 +1,6 @@
 /*-
+ * Copyright 2018 Toomas Soome <tsoome@me.com>
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:

Modified: stable/11/stand/i386/libi386/biosdisk.c
==============================================================================
--- stable/11/stand/i386/libi386/biosdisk.c	Sun Apr 21 03:30:47 2019	(r346475)
+++ stable/11/stand/i386/libi386/biosdisk.c	Sun Apr 21 03:36:05 2019	(r346476)
@@ -40,9 +40,11 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/disk.h>
 #include <sys/limits.h>
+#include <sys/queue.h>
 #include <stand.h>
 #include <machine/bootinfo.h>
 #include <stdarg.h>
+#include <stdbool.h>
 
 #include <bootstrap.h>
 #include <btxv86.h>
@@ -59,6 +61,8 @@ __FBSDID("$FreeBSD$");
 #define	WFDMAJOR	1
 #define	FDMAJOR		2
 #define	DAMAJOR		4
+#define	ACDMAJOR	117
+#define	CDMAJOR		15
 
 #ifdef DISK_DEBUG
 #define	DEBUG(fmt, args...)	printf("%s: " fmt "\n", __func__, ## args)
@@ -66,12 +70,27 @@ __FBSDID("$FreeBSD$");
 #define	DEBUG(fmt, args...)
 #endif
 
+struct specification_packet {
+	uint8_t		sp_size;
+	uint8_t		sp_bootmedia;
+	uint8_t		sp_drive;
+	uint8_t		sp_controller;
+	uint32_t	sp_lba;
+	uint16_t	sp_devicespec;
+	uint16_t	sp_buffersegment;
+	uint16_t	sp_loadsegment;
+	uint16_t	sp_sectorcount;
+	uint16_t	sp_cylsec;
+	uint8_t		sp_head;
+};
+
 /*
  * List of BIOS devices, translation from disk unit number to
  * BIOS unit number.
  */
-static struct bdinfo
+typedef struct bdinfo
 {
+	STAILQ_ENTRY(bdinfo)	bd_link;	/* link in device list */
 	int		bd_unit;	/* BIOS unit number */
 	int		bd_cyl;		/* BIOS geometry */
 	int		bd_hds;
@@ -83,25 +102,30 @@ static struct bdinfo
 #define	BD_MODEEDD	(BD_MODEEDD1 | BD_MODEEDD3)
 #define	BD_MODEMASK	0x0003
 #define	BD_FLOPPY	0x0004
-#define	BD_NO_MEDIA	0x0008
+#define	BD_CDROM	0x0008
+#define	BD_NO_MEDIA	0x0010
 	int		bd_type;	/* BIOS 'drive type' (floppy only) */
 	uint16_t	bd_sectorsize;	/* Sector size */
 	uint64_t	bd_sectors;	/* Disk size */
 	int		bd_open;	/* reference counter */
 	void		*bd_bcache;	/* buffer cache data */
-} bdinfo [MAXBDDEV];
-static int nbdinfo = 0;
+} bdinfo_t;
 
-#define	BD(dev)		(bdinfo[(dev)->dd.d_unit])
 #define	BD_RD		0
 #define	BD_WR		1
 
-static void bd_io_workaround(struct disk_devdesc *dev);
+typedef STAILQ_HEAD(bdinfo_list, bdinfo) bdinfo_list_t;
+static bdinfo_list_t fdinfo = STAILQ_HEAD_INITIALIZER(fdinfo);
+static bdinfo_list_t cdinfo = STAILQ_HEAD_INITIALIZER(cdinfo);
+static bdinfo_list_t hdinfo = STAILQ_HEAD_INITIALIZER(hdinfo);
 
-static int bd_io(struct disk_devdesc *, daddr_t, int, caddr_t, int);
-static int bd_int13probe(struct bdinfo *bd);
+static void bd_io_workaround(bdinfo_t *);
+static int bd_io(struct disk_devdesc *, bdinfo_t *, daddr_t, int, caddr_t, int);
+static bool bd_int13probe(bdinfo_t *);
 
 static int bd_init(void);
+static int cd_init(void);
+static int fd_init(void);
 static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
     char *buf, size_t *rsize);
 static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size,
@@ -110,90 +134,292 @@ static int bd_open(struct open_file *f, ...);
 static int bd_close(struct open_file *f);
 static int bd_ioctl(struct open_file *f, u_long cmd, void *data);
 static int bd_print(int verbose);
+static int cd_print(int verbose);
+static int fd_print(int verbose);
+static void bd_reset_disk(int);
+static int bd_get_diskinfo_std(struct bdinfo *);
 
-struct devsw biosdisk = {
-	"disk",
-	DEVT_DISK,
-	bd_init,
-	bd_strategy,
-	bd_open,
-	bd_close,
-	bd_ioctl,
-	bd_print,
-	NULL
+struct devsw biosfd = {
+	.dv_name = "fd",
+	.dv_type = DEVT_FD,
+	.dv_init = fd_init,
+	.dv_strategy = bd_strategy,
+	.dv_open = bd_open,
+	.dv_close = bd_close,
+	.dv_ioctl = bd_ioctl,
+	.dv_print = fd_print,
+	.dv_cleanup = NULL
 };
 
+struct devsw bioscd = {
+	.dv_name = "cd",
+	.dv_type = DEVT_CD,
+	.dv_init = cd_init,
+	.dv_strategy = bd_strategy,
+	.dv_open = bd_open,
+	.dv_close = bd_close,
+	.dv_ioctl = bd_ioctl,
+	.dv_print = cd_print,
+	.dv_cleanup = NULL
+};
+
+struct devsw bioshd = {
+	.dv_name = "disk",
+	.dv_type = DEVT_DISK,
+	.dv_init = bd_init,
+	.dv_strategy = bd_strategy,
+	.dv_open = bd_open,
+	.dv_close = bd_close,
+	.dv_ioctl = bd_ioctl,
+	.dv_print = bd_print,
+	.dv_cleanup = NULL
+};
+
+static bdinfo_list_t *
+bd_get_bdinfo_list(struct devsw *dev)
+{
+	if (dev->dv_type == DEVT_DISK)
+		return (&hdinfo);
+	if (dev->dv_type == DEVT_CD)
+		return (&cdinfo);
+	if (dev->dv_type == DEVT_FD)
+		return (&fdinfo);
+	return (NULL);
+}
+
+/* XXX this gets called way way too often, investigate */
+static bdinfo_t *
+bd_get_bdinfo(struct devdesc *dev)
+{
+	bdinfo_list_t *bdi;
+	bdinfo_t *bd = NULL;
+	int unit;
+
+	bdi = bd_get_bdinfo_list(dev->d_dev);
+	if (bdi == NULL)
+		return (bd);
+
+	unit = 0;
+	STAILQ_FOREACH(bd, bdi, bd_link) {
+		if (unit == dev->d_unit)
+			return (bd);
+		unit++;
+	}
+	return (bd);
+}
+
 /*
  * Translate between BIOS device numbers and our private unit numbers.
  */
 int
 bd_bios2unit(int biosdev)
 {
-	int i;
+	bdinfo_list_t *bdi[] = { &fdinfo, &cdinfo, &hdinfo, NULL };
+	bdinfo_t *bd;
+	int i, unit;
 
 	DEBUG("looking for bios device 0x%x", biosdev);
-	for (i = 0; i < nbdinfo; i++) {
-		DEBUG("bd unit %d is BIOS device 0x%x", i, bdinfo[i].bd_unit);
-		if (bdinfo[i].bd_unit == biosdev)
-			return (i);
+	for (i = 0; bdi[i] != NULL; i++) {
+		unit = 0;
+		STAILQ_FOREACH(bd, bdi[i], bd_link) {
+			if (bd->bd_unit == biosdev) {
+				DEBUG("bd unit %d is BIOS device 0x%x", unit,
+				    bd->bd_unit);
+				return (unit);
+			}
+			unit++;
+		}
 	}
 	return (-1);
 }
 
 int
-bd_unit2bios(int unit)
+bd_unit2bios(struct i386_devdesc *dev)
 {
+	bdinfo_list_t *bdi;
+	bdinfo_t *bd;
+	int unit;
 
-	if ((unit >= 0) && (unit < nbdinfo))
-		return (bdinfo[unit].bd_unit);
+	bdi = bd_get_bdinfo_list(dev->dd.d_dev);
+	if (bdi == NULL)
+		return (-1);
+
+	unit = 0;
+	STAILQ_FOREACH(bd, bdi, bd_link) {
+		if (unit == dev->dd.d_unit)
+			return (bd->bd_unit);
+		unit++;
+	}
 	return (-1);
 }
 
 /*
+ * Use INT13 AH=15 - Read Drive Type.
+ */
+static int
+fd_count(void)
+{
+	int drive;
+
+	for (drive = 0; drive < MAXBDDEV; drive++) {
+		bd_reset_disk(drive);
+
+		v86.ctl = V86_FLAGS;
+		v86.addr = 0x13;
+		v86.eax = 0x1500;
+		v86.edx = drive;
+		v86int();
+
+		if (V86_CY(v86.efl))
+			break;
+
+		if ((v86.eax & 0x300) == 0)
+			break;
+	}
+
+	return (drive);
+}
+
+/*
  * Quiz the BIOS for disk devices, save a little info about them.
  */
 static int
-bd_init(void)
+fd_init(void)
 {
-	int base, unit, nfd = 0;
+	int unit, numfd;
+	bdinfo_t *bd;
 
-	/* sequence 0, 0x80 */
-	for (base = 0; base <= 0x80; base += 0x80) {
-		for (unit = base; (nbdinfo < MAXBDDEV); unit++) {
-#ifndef VIRTUALBOX
-			/*
-			 * Check the BIOS equipment list for number
-			 * of fixed disks.
-			 */
-			if (base == 0x80 &&
-			    (nfd >= *(unsigned char *)PTOV(BIOS_NUMDRIVES)))
-				break;
-#endif
-			bdinfo[nbdinfo].bd_open = 0;
-			bdinfo[nbdinfo].bd_bcache = NULL;
-			bdinfo[nbdinfo].bd_unit = unit;
-			bdinfo[nbdinfo].bd_flags = unit < 0x80 ? BD_FLOPPY: 0;
-			if (!bd_int13probe(&bdinfo[nbdinfo]))
-				break;
+	numfd = fd_count();
+	for (unit = 0; unit < numfd; unit++) {
+		if ((bd = calloc(1, sizeof(*bd))) == NULL)
+			break;
 
-			/* XXX we need "disk aliases" to make this simpler */
-			printf("BIOS drive %c: is disk%d\n", (unit < 0x80) ?
-			    ('A' + unit): ('C' + unit - 0x80), nbdinfo);
-			nbdinfo++;
-			if (base == 0x80)
-				nfd++;
+		bd->bd_sectorsize = BIOSDISK_SECSIZE;
+		bd->bd_flags = BD_FLOPPY;
+		bd->bd_unit = unit;
+
+		/* Use std diskinfo for floppy drive */
+		if (bd_get_diskinfo_std(bd) != 0) {
+			free(bd);
+			break;
 		}
+		if (bd->bd_sectors == 0)
+			bd->bd_flags |= BD_NO_MEDIA;
+
+		printf("BIOS drive %c: is %s%d\n", ('A' + unit),
+		    biosfd.dv_name, unit);
+
+		STAILQ_INSERT_TAIL(&fdinfo, bd, bd_link);
 	}
-	bcache_add_dev(nbdinfo);
+
+	bcache_add_dev(unit);
 	return (0);
 }
 
+static int
+bd_init(void)
+{
+	int base, unit;
+	bdinfo_t *bd;
+
+	base = 0x80;
+	for (unit = 0; unit < *(unsigned char *)PTOV(BIOS_NUMDRIVES); unit++) {
+		/*
+		 * Check the BIOS equipment list for number of fixed disks.
+		 */
+		if ((bd = calloc(1, sizeof(*bd))) == NULL)
+			break;
+		bd->bd_unit = base + unit;
+		if (!bd_int13probe(bd)) {
+			free(bd);
+			break;
+		}
+
+		printf("BIOS drive %c: is %s%d\n", ('C' + unit),
+		    bioshd.dv_name, unit);
+
+		STAILQ_INSERT_TAIL(&hdinfo, bd, bd_link);
+	}
+	bcache_add_dev(unit);
+	return (0);
+}
+
 /*
+ * We can't quiz, we have to be told what device to use, so this function
+ * doesn't do anything.  Instead, the loader calls bc_add() with the BIOS
+ * device number to add.
+ */
+static int
+cd_init(void)
+{
+
+	return (0);
+}
+
+int
+bc_add(int biosdev)
+{
+	bdinfo_t *bd;
+	struct specification_packet bc_sp;
+	int nbcinfo = 0;
+
+	if (!STAILQ_EMPTY(&cdinfo))
+                return (-1);
+
+        v86.ctl = V86_FLAGS;
+        v86.addr = 0x13;
+        v86.eax = 0x4b01;
+        v86.edx = biosdev;
+        v86.ds = VTOPSEG(&bc_sp);
+        v86.esi = VTOPOFF(&bc_sp);
+        v86int();
+        if ((v86.eax & 0xff00) != 0)
+                return (-1);
+
+	if ((bd = calloc(1, sizeof(*bd))) == NULL)
+		return (-1);
+
+	bd->bd_flags = BD_CDROM;
+        bd->bd_unit = biosdev;
+
+	/*
+	 * Ignore result from bd_int13probe(), we will use local
+	 * workaround below.
+	 */
+	(void)bd_int13probe(bd);
+
+	if (bd->bd_cyl == 0) {
+		bd->bd_cyl = ((bc_sp.sp_cylsec & 0xc0) << 2) +
+		    ((bc_sp.sp_cylsec & 0xff00) >> 8) + 1;
+	}
+	if (bd->bd_hds == 0)
+		bd->bd_hds = bc_sp.sp_head + 1;
+	if (bd->bd_sec == 0)
+		bd->bd_sec = bc_sp.sp_cylsec & 0x3f;
+	if (bd->bd_sectors == 0)
+		bd->bd_sectors = (uint64_t)bd->bd_cyl * bd->bd_hds * bd->bd_sec;
+
+	/* Still no size? use 7.961GB */
+	if (bd->bd_sectors == 0)
+		bd->bd_sectors = 4173824;
+
+	STAILQ_INSERT_TAIL(&cdinfo, bd, bd_link);
+        printf("BIOS CD is cd%d\n", nbcinfo);
+        nbcinfo++;
+        bcache_add_dev(nbcinfo);        /* register cd device in bcache */
+        return(0);
+}
+
+/*
  * Return EDD version or 0 if EDD is not supported on this drive.
  */
 static int
 bd_check_extensions(int unit)
 {
+	/* do not use ext calls for floppy devices */
+	if (unit < 0x80)
+		return (0);
+
 	/* Determine if we can use EDD with this device. */
 	v86.ctl = V86_FLAGS;
 	v86.addr = 0x13;
@@ -281,10 +507,10 @@ bd_get_diskinfo_ext(struct bdinfo *bd)
 	 * 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.
+	 * 16K is largest read buffer we can use at this time.
 	 */
 	if (params.sector_size >= 512 &&
-	    params.sector_size <= 4096 &&
+	    params.sector_size <= 16384 &&
 	    (params.sector_size % BIOSDISK_SECSIZE) == 0)
 		bd->bd_sectorsize = params.sector_size;
 
@@ -306,11 +532,10 @@ bd_get_diskinfo_ext(struct bdinfo *bd)
 /*
  * Try to detect a device supported by the legacy int13 BIOS
  */
-static int
-bd_int13probe(struct bdinfo *bd)
+static bool
+bd_int13probe(bdinfo_t *bd)
 {
-	int edd;
-	int ret;
+	int edd, ret;
 
 	bd->bd_flags &= ~BD_NO_MEDIA;
 
@@ -340,7 +565,7 @@ bd_int13probe(struct bdinfo *bd)
 		v86.edx = bd->bd_unit;
 		v86int();
 		if (V86_CY(v86.efl) || (v86.eax & 0x300) == 0)
-			return (0);
+			return (false);
 	}
 
 	ret = 1;
@@ -354,7 +579,6 @@ bd_int13probe(struct bdinfo *bd)
 		bd->bd_cyl = 80;
 		bd->bd_hds = 2;
 		bd->bd_sec = 18;
-		bd->bd_type = 4;
 		bd->bd_sectors = 2880;
 		/* Since we are there, there most likely is no media */
 		bd->bd_flags |= BD_NO_MEDIA;
@@ -362,6 +586,10 @@ bd_int13probe(struct bdinfo *bd)
 	}
 
 	if (ret != 0) {
+		/* CD is special case, bc_add() has its own fallback. */
+		if ((bd->bd_flags & BD_CDROM) != 0)
+			return (true);
+
 		if (bd->bd_sectors != 0 && edd != 0) {
 			bd->bd_sec = 63;
 			bd->bd_hds = 255;
@@ -369,9 +597,18 @@ bd_int13probe(struct bdinfo *bd)
 			    (bd->bd_sectors + bd->bd_sec * bd->bd_hds - 1) /
 			    bd->bd_sec * bd->bd_hds;
 		} else {
+			const char *dv_name;
+
+			if ((bd->bd_flags & BD_FLOPPY) != 0)
+				dv_name = biosfd.dv_name;
+			else if ((bd->bd_flags & BD_CDROM) != 0)
+				dv_name = bioscd.dv_name;
+			else
+				dv_name = bioshd.dv_name;
+
 			printf("Can not get information about %s unit %#x\n",
-			    biosdisk.dv_name, bd->bd_unit);
-			return (0);
+			    dv_name, bd->bd_unit);
+			return (false);
 		}
 	}
 
@@ -383,54 +620,86 @@ bd_int13probe(struct bdinfo *bd)
 	if (bd->bd_sectors == 0)
 		bd->bd_sectors = (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,
+	DEBUG("unit 0x%x geometry %d/%d/%d\n", bd->bd_unit, bd->bd_cyl,
 	    bd->bd_hds, bd->bd_sec);
 
-	return (1);
+	return (true);
 }
 
+static int
+bd_count(bdinfo_list_t *bdi)
+{
+	bdinfo_t *bd;
+	int i;
+
+	i = 0;
+	STAILQ_FOREACH(bd, bdi, bd_link)
+		i++;
+	return (i);
+}
+
 /*
  * Print information about disks
  */
 static int
-bd_print(int verbose)
+bd_print_common(struct devsw *dev, bdinfo_list_t *bdi, int verbose)
 {
-	static char line[80];
-	struct disk_devdesc dev;
+	char line[80];
+	struct disk_devdesc devd;
+	bdinfo_t *bd;
 	int i, ret = 0;
+	char drive;
 
-	if (nbdinfo == 0)
+	if (STAILQ_EMPTY(bdi))
 		return (0);
 
-	printf("%s devices:", biosdisk.dv_name);
+	printf("%s devices:", dev->dv_name);
 	if ((ret = pager_output("\n")) != 0)
 		return (ret);
 
-	for (i = 0; i < nbdinfo; i++) {
+	i = -1;
+	STAILQ_FOREACH(bd, bdi, bd_link) {
+		i++;
+
+		switch (dev->dv_type) {
+		case DEVT_FD:
+			drive = 'A';
+			break;
+		case DEVT_CD:
+			drive = 'C' + bd_count(&hdinfo);
+			break;
+		default:
+			drive = 'C';
+			break;
+		}
+
 		snprintf(line, sizeof(line),
-		    "    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) == BD_NO_MEDIA ?
+		    "    %s%d:   BIOS drive %c (%s%ju X %u):\n",
+		    dev->dv_name, i, drive + i,
+		    (bd->bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA ?
 		    "no media, " : "",
-		    (uintmax_t)bdinfo[i].bd_sectors,
-		    bdinfo[i].bd_sectorsize);
+		    (uintmax_t)bd->bd_sectors,
+		    bd->bd_sectorsize);
 		if ((ret = pager_output(line)) != 0)
 			break;
 
-		if ((bdinfo[i].bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
+		if ((bd->bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
 			continue;
 
-		dev.dd.d_dev = &biosdisk;
-		dev.dd.d_unit = i;
-		dev.d_slice = -1;
-		dev.d_partition = -1;
-		if (disk_open(&dev,
-		    bdinfo[i].bd_sectorsize * bdinfo[i].bd_sectors,
-		    bdinfo[i].bd_sectorsize) == 0) {
-			snprintf(line, sizeof(line), "    disk%d", i);
-			ret = disk_print(&dev, line, verbose);
-			disk_close(&dev);
+		if (dev->dv_type != DEVT_DISK)
+			continue;
+
+		devd.dd.d_dev = dev;
+		devd.dd.d_unit = i;
+		devd.d_slice = -1;
+		devd.d_partition = -1;
+		if (disk_open(&devd,
+		    bd->bd_sectorsize * bd->bd_sectors,
+		    bd->bd_sectorsize) == 0) {
+			snprintf(line, sizeof(line), "    %s%d",
+			    dev->dv_name, i);
+			ret = disk_print(&devd, line, verbose);
+			disk_close(&devd);
 			if (ret != 0)
 				break;
 		}
@@ -438,6 +707,24 @@ bd_print(int verbose)
 	return (ret);
 }
 
+static int
+fd_print(int verbose)
+{
+	return (bd_print_common(&biosfd, &fdinfo, verbose));
+}
+
+static int
+bd_print(int verbose)
+{
+	return (bd_print_common(&bioshd, &hdinfo, verbose));
+}
+
+static int
+cd_print(int verbose)
+{
+	return (bd_print_common(&bioscd, &cdinfo, verbose));
+}
+
 /*
  * Read disk size from partition.
  * This is needed to work around buggy BIOS systems returning
@@ -448,21 +735,26 @@ bd_print(int verbose)
 static uint64_t
 bd_disk_get_sectors(struct disk_devdesc *dev)
 {
+	bdinfo_t *bd;
 	struct disk_devdesc disk;
 	uint64_t size;
 
+	bd = bd_get_bdinfo(&dev->dd);
+	if (bd == NULL)
+		return (0);
+
 	disk.dd.d_dev = dev->dd.d_dev;
 	disk.dd.d_unit = dev->dd.d_unit;
 	disk.d_slice = -1;
 	disk.d_partition = -1;
 	disk.d_offset = 0;
 
-	size = BD(dev).bd_sectors * BD(dev).bd_sectorsize;
-	if (disk_open(&disk, size, BD(dev).bd_sectorsize) == 0) {
+	size = bd->bd_sectors * bd->bd_sectorsize;
+	if (disk_open(&disk, size, bd->bd_sectorsize) == 0) {
 		(void) disk_ioctl(&disk, DIOCGMEDIASIZE, &size);
 		disk_close(&disk);
 	}
-	return (size / BD(dev).bd_sectorsize);
+	return (size / bd->bd_sectorsize);
 }
 
 /*
@@ -478,6 +770,7 @@ bd_disk_get_sectors(struct disk_devdesc *dev)
 static int
 bd_open(struct open_file *f, ...)
 {
+	bdinfo_t *bd;
 	struct disk_devdesc *dev;
 	va_list ap;
 	int rc;
@@ -486,29 +779,33 @@ bd_open(struct open_file *f, ...)
 	dev = va_arg(ap, struct disk_devdesc *);
 	va_end(ap);
 
-	if (dev->dd.d_unit < 0 || dev->dd.d_unit >= nbdinfo)
+	bd = bd_get_bdinfo(&dev->dd);
+	if (bd == NULL)
 		return (EIO);
 
-	if ((BD(dev).bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA) {
-		if (!bd_int13probe(&BD(dev)))
+	if ((bd->bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA) {
+		if (!bd_int13probe(bd))
 			return (EIO);
-		if ((BD(dev).bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
+		if ((bd->bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
 			return (EIO);
 	}
-	if (BD(dev).bd_bcache == NULL)
-	    BD(dev).bd_bcache = bcache_allocate();
+	if (bd->bd_bcache == NULL)
+	    bd->bd_bcache = bcache_allocate();
 
-	if (BD(dev).bd_open == 0)
-		BD(dev).bd_sectors = bd_disk_get_sectors(dev);
-	BD(dev).bd_open++;
+	if (bd->bd_open == 0)
+		bd->bd_sectors = bd_disk_get_sectors(dev);
+	bd->bd_open++;
 
-	rc = disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
-	    BD(dev).bd_sectorsize);
-	if (rc != 0) {
-		BD(dev).bd_open--;
-		if (BD(dev).bd_open == 0) {
-			bcache_free(BD(dev).bd_bcache);
-			BD(dev).bd_bcache = NULL;
+	rc = 0;
+	if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+		rc = disk_open(dev, bd->bd_sectors * bd->bd_sectorsize,
+		    bd->bd_sectorsize);
+		if (rc != 0) {
+			bd->bd_open--;
+			if (bd->bd_open == 0) {
+				bcache_free(bd->bd_bcache);
+				bd->bd_bcache = NULL;
+			}
 		}
 	}
 	return (rc);
@@ -518,34 +815,48 @@ static int
 bd_close(struct open_file *f)
 {
 	struct disk_devdesc *dev;
+	bdinfo_t *bd;
+	int rc = 0;
 
 	dev = (struct disk_devdesc *)f->f_devdata;
-	BD(dev).bd_open--;
-	if (BD(dev).bd_open == 0) {
-	    bcache_free(BD(dev).bd_bcache);
-	    BD(dev).bd_bcache = NULL;
+	bd = bd_get_bdinfo(&dev->dd);
+	if (bd == NULL)
+		return (EIO);
+
+	bd->bd_open--;
+	if (bd->bd_open == 0) {
+	    bcache_free(bd->bd_bcache);
+	    bd->bd_bcache = NULL;
 	}
-	return (disk_close(dev));
+	if (dev->dd.d_dev->dv_type == DEVT_DISK)
+		rc = disk_close(dev);
+	return (rc);
 }
 
 static int
 bd_ioctl(struct open_file *f, u_long cmd, void *data)
 {
+	bdinfo_t *bd;
 	struct disk_devdesc *dev;
 	int rc;
 
 	dev = (struct disk_devdesc *)f->f_devdata;
+	bd = bd_get_bdinfo(&dev->dd);
+	if (bd == NULL)
+		return (EIO);
 
-	rc = disk_ioctl(dev, cmd, data);
-	if (rc != ENOTTY)
-		return (rc);
+	if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+		rc = disk_ioctl(dev, cmd, data);
+		if (rc != ENOTTY)
+			return (rc);
+	}
 
 	switch (cmd) {
 	case DIOCGSECTORSIZE:
-		*(uint32_t *)data = BD(dev).bd_sectorsize;
+		*(uint32_t *)data = bd->bd_sectorsize;
 		break;
 	case DIOCGMEDIASIZE:
-		*(uint64_t *)data = BD(dev).bd_sectors * BD(dev).bd_sectorsize;
+		*(uint64_t *)data = bd->bd_sectors * bd->bd_sectorsize;
 		break;
 	default:
 		return (ENOTTY);
@@ -557,14 +868,27 @@ static int
 bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
     char *buf, size_t *rsize)
 {
+	bdinfo_t *bd;
 	struct bcache_devdata bcd;
 	struct disk_devdesc *dev;
+	daddr_t offset;
 
 	dev = (struct disk_devdesc *)devdata;
+	bd = bd_get_bdinfo(&dev->dd);
+	if (bd == NULL)
+		return (EINVAL);
+
 	bcd.dv_strategy = bd_realstrategy;
 	bcd.dv_devdata = devdata;
-	bcd.dv_cache = BD(dev).bd_bcache;
-	return (bcache_strategy(&bcd, rw, dblk + dev->d_offset, size,
+	bcd.dv_cache = bd->bd_bcache;
+
+	offset = 0;
+	if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+
+		offset = dev->d_offset * bd->bd_sectorsize;
+		offset /= BIOSDISK_SECSIZE;
+	}
+	return (bcache_strategy(&bcd, rw, dblk + offset, size,
 	    buf, rsize));
 }
 
@@ -573,12 +897,14 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
     char *buf, size_t *rsize)
 {
 	struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
-	uint64_t disk_blocks, offset;
-	size_t blks, blkoff, bsize, rest;
-	caddr_t bbuf;
+	bdinfo_t *bd;
+	uint64_t disk_blocks, offset, d_offset;
+	size_t blks, blkoff, bsize, bio_size, rest;
+	caddr_t bbuf = NULL;
 	int rc;
 
-	if ((BD(dev).bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
+	bd = bd_get_bdinfo(&dev->dd);
+	if (bd == NULL || (bd->bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
 		return (EIO);
 
 	/*
@@ -596,8 +922,8 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
 	DEBUG("open_disk %p", dev);
 
 	offset = dblk * BIOSDISK_SECSIZE;
-	dblk = offset / BD(dev).bd_sectorsize;
-	blkoff = offset % BD(dev).bd_sectorsize;
+	dblk = offset / bd->bd_sectorsize;
+	blkoff = offset % bd->bd_sectorsize;
 
 	/*
 	 * Check the value of the size argument. We do have quite small
@@ -610,8 +936,8 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
 		return (EIO);
 	}
 
-	blks = size / BD(dev).bd_sectorsize;
-	if (blks == 0 || (size % BD(dev).bd_sectorsize) != 0)
+	blks = size / bd->bd_sectorsize;
+	if (blks == 0 || (size % bd->bd_sectorsize) != 0)
 		blks++;
 
 	if (dblk > dblk + blks)
@@ -624,45 +950,62 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
 	 * Get disk blocks, this value is either for whole disk or for
 	 * partition.
 	 */
-	if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
-		/* DIOCGMEDIASIZE does return bytes. */
-		disk_blocks /= BD(dev).bd_sectorsize;
-	} else {
-		/* We should not get here. Just try to survive. */
-		disk_blocks = BD(dev).bd_sectors - dev->d_offset;
+	d_offset = 0;
+	disk_blocks = 0;
+	if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+		if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
+			/* DIOCGMEDIASIZE does return bytes. */
+			disk_blocks /= bd->bd_sectorsize;
+		}
+		d_offset = dev->d_offset;
 	}
+	if (disk_blocks == 0)
+		disk_blocks = bd->bd_sectors - d_offset;
 
 	/* Validate source block address. */
-	if (dblk < dev->d_offset || dblk >= dev->d_offset + disk_blocks)
+	if (dblk < d_offset || dblk >= d_offset + disk_blocks)
 		return (EIO);
 
 	/*
 	 * Truncate if we are crossing disk or partition end.
 	 */
-	if (dblk + blks >= dev->d_offset + disk_blocks) {
-		blks = dev->d_offset + disk_blocks - dblk;
-		size = blks * BD(dev).bd_sectorsize;
+	if (dblk + blks >= d_offset + disk_blocks) {
+		blks = d_offset + disk_blocks - dblk;
+		size = blks * bd->bd_sectorsize;
 		DEBUG("short I/O %d", blks);
 	}
 
-	if (V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize == 0)
-		panic("BUG: Real mode buffer is too small\n");
+	bio_size = min(BIO_BUFFER_SIZE, size);
+	while (bio_size > bd->bd_sectorsize) {
+		bbuf = bio_alloc(bio_size);
+		if (bbuf != NULL)
+			break;
+		bio_size -= bd->bd_sectorsize;
+	}
+	if (bbuf == NULL) {
+		bio_size = V86_IO_BUFFER_SIZE;
+		if (bio_size / bd->bd_sectorsize == 0)
+			panic("BUG: Real mode buffer is too small");
 
-	bbuf = PTOV(V86_IO_BUFFER);
+		/* Use alternate 4k buffer */
+		bbuf = PTOV(V86_IO_BUFFER);
+	}
 	rest = size;
-
+	rc = 0;
 	while (blks > 0) {
-		int x = min(blks, V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize);
+		int x = min(blks, bio_size / bd->bd_sectorsize);
 
 		switch (rw & F_MASK) {
 		case F_READ:
 			DEBUG("read %d from %lld to %p", x, dblk, buf);
-			bsize = BD(dev).bd_sectorsize * x - blkoff;
+			bsize = bd->bd_sectorsize * x - blkoff;
 			if (rest < bsize)
 				bsize = rest;
 
-			if ((rc = bd_io(dev, dblk, x, bbuf, BD_RD)) != 0)
-				return (EIO);
+			if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD)) != 0) {
+				rc = EIO;
+				goto error;
+			}
 
 			bcopy(bbuf + blkoff, buf, bsize);
 			break;
@@ -674,33 +1017,36 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
 				 * bbuf.
 				 */
 				x = 1;
-				bsize = BD(dev).bd_sectorsize - blkoff;
+				bsize = bd->bd_sectorsize - blkoff;
 				bsize = min(bsize, rest);
-				rc = bd_io(dev, dblk, x, bbuf, BD_RD);
-			} else if (rest < BD(dev).bd_sectorsize) {
+				rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD);
+			} else if (rest < bd->bd_sectorsize) {
 				/*
 				 * The remaining block is not full

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904210336.x3L3a634020498>