svn commit: r341328 - in head/stand/i386: libi386 loader

Toomas Soome tsoome at FreeBSD.org
Fri Nov 30 08:01:13 UTC 2018


Author: tsoome
Date: Fri Nov 30 08:01:11 2018
New Revision: 341328
URL: https://svnweb.freebsd.org/changeset/base/341328

Log:
  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).
  
  Differential Revision:	https://reviews.freebsd.org/D17888

Deleted:
  head/stand/i386/libi386/bioscd.c
Modified:
  head/stand/i386/libi386/Makefile
  head/stand/i386/libi386/biosdisk.c
  head/stand/i386/libi386/bootinfo32.c
  head/stand/i386/libi386/libi386.h
  head/stand/i386/loader/chain.c
  head/stand/i386/loader/conf.c
  head/stand/i386/loader/main.c

Modified: head/stand/i386/libi386/Makefile
==============================================================================
--- head/stand/i386/libi386/Makefile	Fri Nov 30 07:11:05 2018	(r341327)
+++ head/stand/i386/libi386/Makefile	Fri Nov 30 08:01:11 2018	(r341328)
@@ -4,7 +4,7 @@
 
 LIB=			i386
 
-SRCS=	biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \
+SRCS=	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 \

Modified: head/stand/i386/libi386/biosdisk.c
==============================================================================
--- head/stand/i386/libi386/biosdisk.c	Fri Nov 30 07:11:05 2018	(r341327)
+++ head/stand/i386/libi386/biosdisk.c	Fri Nov 30 08:01:11 2018	(r341328)
@@ -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,42 +134,120 @@ 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);
 
-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);
 }
 
@@ -153,42 +255,128 @@ bd_unit2bios(int unit)
  * 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;
+	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;
+	for (unit = 0; unit < MAXBDDEV; unit++) {
+		if ((bd = calloc(1, sizeof(*bd))) == NULL)
+			break;
+		bd->bd_flags = BD_FLOPPY;
+		bd->bd_unit = unit;
+		if (!bd_int13probe(bd)) {
+			free(bd);
+			break;
+		}
+		if (bd->bd_sectors == 0)
+			bd->bd_flags |= BD_NO_MEDIA;
 
-			/* 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++;
+		printf("BIOS drive %c: is %s%d\n", ('A' + unit),
+		    biosfd.dv_name, unit);
+
+		STAILQ_INSERT_TAIL(&fdinfo, bd, bd_link);
+	}
+
+	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(nbdinfo);
+	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
@@ -306,11 +494,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 +527,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 +541,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 +548,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 +559,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 +582,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 +669,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 +697,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 +732,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 +741,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 +777,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 +830,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 +859,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;
+	bdinfo_t *bd;
+	uint64_t disk_blocks, offset, d_offset;
 	size_t blks, blkoff, bsize, rest;
 	caddr_t bbuf;
 	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 +884,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 +898,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,44 +912,48 @@ 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)
+	if (V86_IO_BUFFER_SIZE / bd->bd_sectorsize == 0)
 		panic("BUG: Real mode buffer is too small");
 
 	bbuf = PTOV(V86_IO_BUFFER);
 	rest = size;
 
 	while (blks > 0) {
-		int x = min(blks, V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize);
+		int x = min(blks, V86_IO_BUFFER_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)
+			if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD)) != 0)
 				return (EIO);
 
 			bcopy(bbuf + blkoff, buf, bsize);
@@ -674,27 +966,27 @@ 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
 				 * sector. Read 1 sector to bbuf.
 				 */
 				x = 1;
 				bsize = rest;
-				rc = bd_io(dev, dblk, x, bbuf, BD_RD);
+				rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD);
 			} else {
 				/* We can write full sector(s). */
-				bsize = BD(dev).bd_sectorsize * x;
+				bsize = bd->bd_sectorsize * x;
 			}
 			/*
 			 * Put your Data In, Put your Data out,
 			 * Put your Data In, and shake it all about
 			 */
 			bcopy(buf, bbuf + blkoff, bsize);
-			if ((rc = bd_io(dev, dblk, x, bbuf, BD_WR)) != 0)
+			if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_WR)) != 0)
 				return (EIO);
 
 			break;
@@ -716,7 +1008,7 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
 }
 
 static int
-bd_edd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
+bd_edd_io(bdinfo_t *bd, daddr_t dblk, int blks, caddr_t dest,
     int dowrite)
 {
 	static struct edd_packet packet;
@@ -733,7 +1025,7 @@ bd_edd_io(struct disk_devdesc *dev, daddr_t dblk, int 
 		v86.eax = 0x4300;
 	else
 		v86.eax = 0x4200;
-	v86.edx = BD(dev).bd_unit;
+	v86.edx = bd->bd_unit;
 	v86.ds = VTOPSEG(&packet);
 	v86.esi = VTOPOFF(&packet);
 	v86int();
@@ -743,17 +1035,17 @@ bd_edd_io(struct disk_devdesc *dev, daddr_t dblk, int 
 }
 
 static int
-bd_chs_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
+bd_chs_io(bdinfo_t *bd, daddr_t dblk, int blks, caddr_t dest,
     int dowrite)
 {
 	uint32_t x, bpc, cyl, hd, sec;
 
-	bpc = BD(dev).bd_sec * BD(dev).bd_hds;	/* blocks per cylinder */
+	bpc = bd->bd_sec * bd->bd_hds;	/* blocks per cylinder */
 	x = dblk;
 	cyl = x / bpc;			/* block # / blocks per cylinder */
 	x %= bpc;				/* block offset into cylinder */
-	hd = x / BD(dev).bd_sec;		/* offset / blocks per track */
-	sec = x % BD(dev).bd_sec;		/* offset into track */
+	hd = x / bd->bd_sec;		/* offset / blocks per track */
+	sec = x % bd->bd_sec;		/* offset into track */
 
 	/* correct sector number for 1-based BIOS numbering */
 	sec++;
@@ -770,7 +1062,7 @@ bd_chs_io(struct disk_devdesc *dev, daddr_t dblk, int 
 	else
 		v86.eax = 0x200 | blks;
 	v86.ecx = ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec;
-	v86.edx = (hd << 8) | BD(dev).bd_unit;
+	v86.edx = (hd << 8) | bd->bd_unit;
 	v86.es = VTOPSEG(dest);
 	v86.ebx = VTOPOFF(dest);
 	v86int();
@@ -780,16 +1072,16 @@ bd_chs_io(struct disk_devdesc *dev, daddr_t dblk, int 
 }
 
 static void
-bd_io_workaround(struct disk_devdesc *dev)
+bd_io_workaround(bdinfo_t *bd)
 {
 	uint8_t buf[8 * 1024];
 
-	bd_edd_io(dev, 0xffffffff, 1, (caddr_t)buf, BD_RD);
+	bd_edd_io(bd, 0xffffffff, 1, (caddr_t)buf, BD_RD);
 }
 
 static int
-bd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
-    int dowrite)
+bd_io(struct disk_devdesc *dev, bdinfo_t *bd, daddr_t dblk, int blks,
+    caddr_t dest, int dowrite)
 {
 	int result, retry;
 
@@ -809,20 +1101,20 @@ bd_io(struct disk_devdesc *dev, daddr_t dblk, int blks
 	 * may also retry.
 	 */
 	if (dowrite == BD_RD && dblk >= 0x100000000)
-		bd_io_workaround(dev);
+		bd_io_workaround(bd);
 	for (retry = 0; retry < 3; retry++) {
-		if (BD(dev).bd_flags & BD_MODEEDD)
-			result = bd_edd_io(dev, dblk, blks, dest, dowrite);
+		if (bd->bd_flags & BD_MODEEDD)
+			result = bd_edd_io(bd, dblk, blks, dest, dowrite);
 		else
-			result = bd_chs_io(dev, dblk, blks, dest, dowrite);
+			result = bd_chs_io(bd, dblk, blks, dest, dowrite);
 
 		if (result == 0) {
-			if (BD(dev).bd_flags & BD_NO_MEDIA)
-				BD(dev).bd_flags &= ~BD_NO_MEDIA;
+			if (bd->bd_flags & BD_NO_MEDIA)
+				bd->bd_flags &= ~BD_NO_MEDIA;

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


More information about the svn-src-all mailing list