199767f8919635c4928607450d9e0abb932109ceToomas Soome/*-
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 2001 John H. Baldwin <jhb@FreeBSD.org>
199767f8919635c4928607450d9e0abb932109ceToomas Soome * All rights reserved.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Redistribution and use in source and binary forms, with or without
199767f8919635c4928607450d9e0abb932109ceToomas Soome * modification, are permitted provided that the following conditions
199767f8919635c4928607450d9e0abb932109ceToomas Soome * are met:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 1. Redistributions of source code must retain the above copyright
199767f8919635c4928607450d9e0abb932109ceToomas Soome * notice, this list of conditions and the following disclaimer.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
199767f8919635c4928607450d9e0abb932109ceToomas Soome * notice, this list of conditions and the following disclaimer in the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * documentation and/or other materials provided with the distribution.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
199767f8919635c4928607450d9e0abb932109ceToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
199767f8919635c4928607450d9e0abb932109ceToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
199767f8919635c4928607450d9e0abb932109ceToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
199767f8919635c4928607450d9e0abb932109ceToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
199767f8919635c4928607450d9e0abb932109ceToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
199767f8919635c4928607450d9e0abb932109ceToomas Soome * SUCH DAMAGE.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/cdefs.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome__FBSDID("$FreeBSD$");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * BIOS CD device handling for CD's that have been booted off of via no
199767f8919635c4928607450d9e0abb932109ceToomas Soome * emulation booting as defined in the El Torito standard.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Ideas and algorithms from:
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * - FreeBSD libi386/biosdisk.c
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <stand.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/param.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <machine/bootinfo.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <stdarg.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <bootstrap.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <btxv86.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <edd.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "libi386.h"
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define BIOSCD_SECSIZE 2048
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define BUFSIZE (1 * BIOSCD_SECSIZE)
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define MAXBCDEV 1
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* Major numbers for devices we frontend for. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define ACDMAJOR 117
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define CDMAJOR 15
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef DISK_DEBUG
199767f8919635c4928607450d9e0abb932109ceToomas Soome# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
199767f8919635c4928607450d9e0abb932109ceToomas Soome#else
199767f8919635c4928607450d9e0abb932109ceToomas Soome# define DEBUG(fmt, args...)
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct specification_packet {
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_char sp_size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_char sp_bootmedia;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_char sp_drive;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_char sp_controller;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_int sp_lba;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_short sp_devicespec;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_short sp_buffersegment;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_short sp_loadsegment;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_short sp_sectorcount;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_short sp_cylsec;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_char sp_head;
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * List of BIOS devices, translation from disk unit number to
199767f8919635c4928607450d9e0abb932109ceToomas Soome * BIOS unit number.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic struct bcinfo {
199767f8919635c4928607450d9e0abb932109ceToomas Soome int bc_unit; /* BIOS unit number */
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct specification_packet bc_sp;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int bc_open; /* reference counter */
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *bc_bcache; /* buffer cache data */
199767f8919635c4928607450d9e0abb932109ceToomas Soome} bcinfo [MAXBCDEV];
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nbcinfo = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define BC(dev) (bcinfo[(dev)->d_unit])
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int bc_read(int unit, daddr_t dblk, int blks, caddr_t dest);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int bc_init(void);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int bc_strategy(void *devdata, int flag, daddr_t dblk,
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t offset, size_t size, char *buf, size_t *rsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int bc_realstrategy(void *devdata, int flag, daddr_t dblk,
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t offset, size_t size, char *buf, size_t *rsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int bc_open(struct open_file *f, ...);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int bc_close(struct open_file *f);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int bc_print(int verbose);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct devsw bioscd = {
199767f8919635c4928607450d9e0abb932109ceToomas Soome "cd",
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEVT_CD,
199767f8919635c4928607450d9e0abb932109ceToomas Soome bc_init,
199767f8919635c4928607450d9e0abb932109ceToomas Soome bc_strategy,
199767f8919635c4928607450d9e0abb932109ceToomas Soome bc_open,
199767f8919635c4928607450d9e0abb932109ceToomas Soome bc_close,
199767f8919635c4928607450d9e0abb932109ceToomas Soome noioctl,
199767f8919635c4928607450d9e0abb932109ceToomas Soome bc_print,
199767f8919635c4928607450d9e0abb932109ceToomas Soome NULL
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Translate between BIOS device numbers and our private unit numbers.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_bios2unit(int biosdev)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome int i;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("looking for bios device 0x%x", biosdev);
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < nbcinfo; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("bc unit %d is BIOS device 0x%x", i, bcinfo[i].bc_unit);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bcinfo[i].bc_unit == biosdev)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(i);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_unit2bios(int unit)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((unit >= 0) && (unit < nbcinfo))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(bcinfo[unit].bc_unit);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * We can't quiz, we have to be told what device to use, so this functoin
199767f8919635c4928607450d9e0abb932109ceToomas Soome * doesn't do anything. Instead, the loader calls bc_add() with the BIOS
199767f8919635c4928607450d9e0abb932109ceToomas Soome * device number to add.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_init(void)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_add(int biosdev)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (nbcinfo >= MAXBCDEV)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcinfo[nbcinfo].bc_unit = biosdev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.ctl = V86_FLAGS;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.addr = 0x13;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.eax = 0x4b01;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.edx = biosdev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.ds = VTOPSEG(&bcinfo[nbcinfo].bc_sp);
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.esi = VTOPOFF(&bcinfo[nbcinfo].bc_sp);
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86int();
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((v86.eax & 0xff00) != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("BIOS CD is cd%d\n", nbcinfo);
199767f8919635c4928607450d9e0abb932109ceToomas Soome nbcinfo++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcache_add_dev(nbcinfo); /* register cd device in bcache */
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Print information about disks
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_print(int verbose)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome char line[80];
199767f8919635c4928607450d9e0abb932109ceToomas Soome int i, ret = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < nbcinfo; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome sprintf(line, " cd%d: Device 0x%x\n", i,
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcinfo[i].bc_sp.sp_devicespec);
199767f8919635c4928607450d9e0abb932109ceToomas Soome ret = pager_output(line);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ret != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ret);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ret);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Attempt to open the disk described by (dev) for use by (f).
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_open(struct open_file *f, ...)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome va_list ap;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct i386_devdesc *dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome va_start(ap, f);
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev = va_arg(ap, struct i386_devdesc *);
199767f8919635c4928607450d9e0abb932109ceToomas Soome va_end(ap);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (dev->d_unit >= nbcinfo) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("attempt to open nonexistent disk");
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(ENXIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome BC(dev).bc_open++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (BC(dev).bc_bcache == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome BC(dev).bc_bcache = bcache_allocate();
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_close(struct open_file *f)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct i386_devdesc *dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev = (struct i386_devdesc *)f->f_devdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome BC(dev).bc_open--;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (BC(dev).bc_open == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcache_free(BC(dev).bc_bcache);
199767f8919635c4928607450d9e0abb932109ceToomas Soome BC(dev).bc_bcache = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *buf, size_t *rsize)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct bcache_devdata bcd;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct i386_devdesc *dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev = (struct i386_devdesc *)devdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcd.dv_strategy = bc_realstrategy;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcd.dv_devdata = devdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcd.dv_cache = BC(dev).bc_bcache;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (bcache_strategy(&bcd, rw, dblk, offset, size, buf, rsize));
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *buf, size_t *rsize)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct i386_devdesc *dev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int unit;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int blks;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef BD_SUPPORT_FRAGS
199767f8919635c4928607450d9e0abb932109ceToomas Soome char fragbuf[BIOSCD_SECSIZE];
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t fragsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fragsize = size % BIOSCD_SECSIZE;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#else
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (size % BIOSCD_SECSIZE)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EINVAL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (rw != F_READ)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(EROFS);
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev = (struct i386_devdesc *)devdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome unit = dev->d_unit;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blks = size / BIOSCD_SECSIZE;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (dblk % (BIOSCD_SECSIZE / DEV_BSIZE) != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EINVAL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome dblk /= (BIOSCD_SECSIZE / DEV_BSIZE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("read %d from %lld to %p", blks, dblk, buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (rsize)
199767f8919635c4928607450d9e0abb932109ceToomas Soome *rsize = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((blks = bc_read(unit, dblk, blks, buf)) < 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("read error");
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (size / BIOSCD_SECSIZE > blks) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (rsize)
199767f8919635c4928607450d9e0abb932109ceToomas Soome *rsize = blks * BIOSCD_SECSIZE;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef BD_SUPPORT_FRAGS
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("frag read %d from %lld+%d to %p",
199767f8919635c4928607450d9e0abb932109ceToomas Soome fragsize, dblk, blks, buf + (blks * BIOSCD_SECSIZE));
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fragsize && bc_read(unit, dblk + blks, 1, fragbuf) != 1) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blks) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (rsize)
199767f8919635c4928607450d9e0abb932109ceToomas Soome *rsize = blks * BIOSCD_SECSIZE;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("frag read error");
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(EIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcopy(fragbuf, buf + (blks * BIOSCD_SECSIZE), fragsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (rsize)
199767f8919635c4928607450d9e0abb932109ceToomas Soome *rsize = size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* Max number of sectors to bounce-buffer at a time. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define CD_BOUNCEBUF 8
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* return negative value for an error, otherwise blocks read */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_int maxfer, resid, result, retry, x;
199767f8919635c4928607450d9e0abb932109ceToomas Soome caddr_t bbuf, p, xp;
199767f8919635c4928607450d9e0abb932109ceToomas Soome static struct edd_packet packet;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int biosdev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef DISK_DEBUG
199767f8919635c4928607450d9e0abb932109ceToomas Soome int error;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Just in case some idiot actually tries to read -1 blocks... */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blks < 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* If nothing to do, just return succcess. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blks == 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Decide whether we have to bounce */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (VTOP(dest) >> 20 != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * The destination buffer is above first 1MB of
199767f8919635c4928607450d9e0abb932109ceToomas Soome * physical memory so we have to arrange a suitable
199767f8919635c4928607450d9e0abb932109ceToomas Soome * bounce buffer.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome x = min(CD_BOUNCEBUF, (unsigned)blks);
199767f8919635c4928607450d9e0abb932109ceToomas Soome bbuf = alloca(x * BIOSCD_SECSIZE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome maxfer = x;
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome bbuf = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome maxfer = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome biosdev = bc_unit2bios(unit);
199767f8919635c4928607450d9e0abb932109ceToomas Soome resid = blks;
199767f8919635c4928607450d9e0abb932109ceToomas Soome p = dest;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (resid > 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bbuf)
199767f8919635c4928607450d9e0abb932109ceToomas Soome xp = bbuf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome else
199767f8919635c4928607450d9e0abb932109ceToomas Soome xp = p;
199767f8919635c4928607450d9e0abb932109ceToomas Soome x = resid;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (maxfer > 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome x = min(x, maxfer);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Loop retrying the operation a couple of times. The BIOS
199767f8919635c4928607450d9e0abb932109ceToomas Soome * may also retry.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (retry = 0; retry < 3; retry++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* If retrying, reset the drive */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (retry > 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.ctl = V86_FLAGS;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.addr = 0x13;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.eax = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.edx = biosdev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86int();
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome packet.len = sizeof(struct edd_packet);
199767f8919635c4928607450d9e0abb932109ceToomas Soome packet.count = x;
199767f8919635c4928607450d9e0abb932109ceToomas Soome packet.off = VTOPOFF(xp);
199767f8919635c4928607450d9e0abb932109ceToomas Soome packet.seg = VTOPSEG(xp);
199767f8919635c4928607450d9e0abb932109ceToomas Soome packet.lba = dblk;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.ctl = V86_FLAGS;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.addr = 0x13;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.eax = 0x4200;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.edx = biosdev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.ds = VTOPSEG(&packet);
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86.esi = VTOPOFF(&packet);
199767f8919635c4928607450d9e0abb932109ceToomas Soome v86int();
199767f8919635c4928607450d9e0abb932109ceToomas Soome result = V86_CY(v86.efl);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (result == 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* fall back to 1 sector read */
199767f8919635c4928607450d9e0abb932109ceToomas Soome x = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef DISK_DEBUG
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = (v86.eax >> 8) & 0xff;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("%d sectors from %lld to %p (0x%x) %s", x, dblk, p,
199767f8919635c4928607450d9e0abb932109ceToomas Soome VTOP(p), result ? "failed" : "ok");
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("unit %d status 0x%x", unit, error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* still an error? break off */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (result != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bbuf != NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcopy(bbuf, p, x * BIOSCD_SECSIZE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome p += (x * BIOSCD_SECSIZE);
199767f8919635c4928607450d9e0abb932109ceToomas Soome dblk += x;
199767f8919635c4928607450d9e0abb932109ceToomas Soome resid -= x;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* hexdump(dest, (blks * BIOSCD_SECSIZE)); */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blks - resid == 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (-1); /* read failed */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (blks - resid);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Return a suitable dev_t value for (dev).
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint
199767f8919635c4928607450d9e0abb932109ceToomas Soomebc_getdev(struct i386_devdesc *dev)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome int biosdev, unit;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int major;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int rootdev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome unit = dev->d_unit;
199767f8919635c4928607450d9e0abb932109ceToomas Soome biosdev = bc_unit2bios(unit);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("unit %d BIOS device %d", unit, biosdev);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (biosdev == -1) /* not a BIOS device */
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * XXX: Need to examine device spec here to figure out if SCSI or
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ATAPI. No idea on how to figure out device number. All we can
199767f8919635c4928607450d9e0abb932109ceToomas Soome * really pass to the kernel is what bus and device on which bus we
199767f8919635c4928607450d9e0abb932109ceToomas Soome * were booted from, which dev_t isn't well suited to since those
199767f8919635c4928607450d9e0abb932109ceToomas Soome * number don't match to unit numbers very well. We may just need
199767f8919635c4928607450d9e0abb932109ceToomas Soome * to engage in a hack where we pass -C to the boot args if we are
199767f8919635c4928607450d9e0abb932109ceToomas Soome * the boot device.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome major = ACDMAJOR;
199767f8919635c4928607450d9e0abb932109ceToomas Soome unit = 0; /* XXX */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* XXX: Assume partition 'a'. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome rootdev = MAKEBOOTDEV(major, 0, unit, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DEBUG("dev is 0x%x\n", rootdev);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(rootdev);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}