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 <[email protected]>
+ *
  * 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 ***


_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to