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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to