From owner-svn-src-all@freebsd.org Sun Apr 21 03:36:08 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id AB3301580291; Sun, 21 Apr 2019 03:36:07 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 5CA4488C2B; Sun, 21 Apr 2019 03:36:07 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 1CE4D1FB76; Sun, 21 Apr 2019 03:36:07 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x3L3a7ev020504; Sun, 21 Apr 2019 03:36:07 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x3L3a634020498; Sun, 21 Apr 2019 03:36:06 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201904210336.x3L3a634020498@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Sun, 21 Apr 2019 03:36:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r346476 - in stable/11/stand: common i386/libfirewire i386/libi386 i386/loader libsa uboot/lib X-SVN-Group: stable-11 X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in stable/11/stand: common i386/libfirewire i386/libi386 i386/loader libsa uboot/lib X-SVN-Commit-Revision: 346476 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 5CA4488C2B X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.96 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.97)[-0.966,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 21 Apr 2019 03:36:08 -0000 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 + * * 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 #include +#include #include #include #include +#include #include #include @@ -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 ***