[BACK]Return to biosdev.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / stand / libsa

Annotation of sys/arch/i386/stand/libsa/biosdev.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: biosdev.c,v 1.72 2007/05/27 00:57:17 tom Exp $        */
                      2:
                      3: /*
                      4:  * Copyright (c) 1996 Michael Shalayeff
                      5:  * Copyright (c) 2003 Tobias Weingartner
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  *
                     17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     18:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     19:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     27:  * SUCH DAMAGE.
                     28:  *
                     29:  */
                     30:
                     31: #include <sys/param.h>
                     32: #include <sys/reboot.h>
                     33: #include <sys/disklabel.h>
                     34: #include <machine/tss.h>
                     35: #include <machine/biosvar.h>
                     36: #include <lib/libsa/saerrno.h>
                     37: #include <isofs/cd9660/iso.h>
                     38: #include "disk.h"
                     39: #include "debug.h"
                     40: #include "libsa.h"
                     41: #include "biosdev.h"
                     42:
                     43: static const char *biosdisk_err(u_int);
                     44: static int biosdisk_errno(u_int);
                     45:
                     46: static int CHS_rw (int, int, int, int, int, int, void *);
                     47: static int EDD_rw (int, int, u_int64_t, u_int32_t, void *);
                     48:
                     49: extern int debug;
                     50: int bios_bootdev;
                     51: int bios_cddev = -1;           /* Set by srt0 if coming from CD */
                     52:
                     53: #if 0
                     54: struct biosdisk {
                     55:        bios_diskinfo_t *bios_info;
                     56:        dev_t   bsddev;
                     57:        struct disklabel disklabel;
                     58: };
                     59: #endif
                     60:
                     61: struct EDD_CB {
                     62:        u_int8_t  edd_len;      /* size of packet */
                     63:        u_int8_t  edd_res1;     /* reserved */
                     64:        u_int8_t  edd_nblk;     /* # of blocks to transfer */
                     65:        u_int8_t  edd_res2;     /* reserved */
                     66:        u_int16_t edd_off;      /* address of buffer (offset) */
                     67:        u_int16_t edd_seg;      /* address of buffer (segment) */
                     68:        u_int64_t edd_daddr;    /* starting block */
                     69: };
                     70:
                     71: /*
                     72:  * reset disk system
                     73:  */
                     74: static int
                     75: biosdreset(int dev)
                     76: {
                     77:        int rv;
                     78:
                     79:        __asm __volatile (DOINT(0x13) "; setc %b0" : "=a" (rv)
                     80:            : "0" (0), "d" (dev) : "%ecx", "cc");
                     81:
                     82:        return ((rv & 0xff)? rv >> 8 : 0);
                     83: }
                     84:
                     85: /*
                     86:  * Fill out a bios_diskinfo_t for this device.
                     87:  * Return 0 if all ok.
                     88:  * Return 1 if not ok.
                     89:  */
                     90: int
                     91: bios_getdiskinfo(int dev, bios_diskinfo_t *pdi)
                     92: {
                     93:        u_int rv;
                     94:
                     95:        /* Just reset, don't check return code */
                     96:        rv = biosdreset(dev);
                     97:
                     98: #ifdef BIOS_DEBUG
                     99:        if (debug)
                    100:                printf("getinfo: try #8, 0x%x, %p\n", dev, pdi);
                    101: #endif
                    102:        __asm __volatile (DOINT(0x13) "\n\t"
                    103:            "setc %b0; movzbl %h1, %1\n\t"
                    104:            "movzbl %%cl, %3; andb $0x3f, %b3\n\t"
                    105:            "xchgb %%cl, %%ch; rolb $2, %%ch"
                    106:            : "=a" (rv), "=d" (pdi->bios_heads),
                    107:              "=c" (pdi->bios_cylinders),
                    108:              "=b" (pdi->bios_sectors)
                    109:            : "0" (0x0800), "1" (dev) : "cc");
                    110:
                    111: #ifdef BIOS_DEBUG
                    112:        if (debug) {
                    113:                printf("getinfo: got #8\n");
                    114:                printf("disk 0x%x: %d,%d,%d\n", dev, pdi->bios_cylinders,
                    115:                    pdi->bios_heads, pdi->bios_sectors);
                    116:        }
                    117: #endif
                    118:        if (rv & 0xff)
                    119:                return 1;
                    120:
                    121:        /* Fix up info */
                    122:        pdi->bios_number = dev;
                    123:        pdi->bios_heads++;
                    124:        pdi->bios_cylinders &= 0x3ff;
                    125:        pdi->bios_cylinders++;
                    126:
                    127:        /* Sanity check */
                    128:        if (!pdi->bios_cylinders || !pdi->bios_heads || !pdi->bios_sectors)
                    129:                return 1;
                    130:
                    131:        /* CD-ROMs sometimes return heads == 1 */
                    132:        if (pdi->bios_heads < 2)
                    133:                return 1;
                    134:
                    135:        /* NOTE:
                    136:         * This currently hangs/reboots some machines
                    137:         * The IBM ThinkPad 750ED for one.
                    138:         *
                    139:         * Funny that an IBM/MS extension would not be
                    140:         * implemented by an IBM system...
                    141:         *
                    142:         * Future hangs (when reported) can be "fixed"
                    143:         * with getSYSCONFaddr() and an exceptions list.
                    144:         */
                    145:        if (dev & 0x80 && (dev == 0x80 || dev == 0x81 || dev == bios_bootdev)) {
                    146:                int bm;
                    147:
                    148: #ifdef BIOS_DEBUG
                    149:                if (debug)
                    150:                        printf("getinfo: try #41, 0x%x\n", dev);
                    151: #endif
                    152:                /* EDD support check */
                    153:                __asm __volatile(DOINT(0x13) "; setc %b0"
                    154:                         : "=a" (rv), "=c" (bm)
                    155:                         : "0" (0x4100), "b" (0x55aa), "d" (dev) : "cc");
                    156:                if (!(rv & 0xff) && (BIOS_regs.biosr_bx & 0xffff) == 0xaa55)
                    157:                        pdi->bios_edd = (bm & 0xffff) | ((rv & 0xff) << 16);
                    158:                else
                    159:                        pdi->bios_edd = -1;
                    160:
                    161: #ifdef BIOS_DEBUG
                    162:                if (debug) {
                    163:                        printf("getinfo: got #41\n");
                    164:                        printf("disk 0x%x: 0x%x\n", dev, bm);
                    165:                }
                    166: #endif
                    167:                /*
                    168:                 * If extended disk access functions are not supported
                    169:                 * there is not much point on doing EDD.
                    170:                 */
                    171:                if (!(pdi->bios_edd & EXT_BM_EDA))
                    172:                        pdi->bios_edd = -1;
                    173:        } else
                    174:                pdi->bios_edd = -1;
                    175:
                    176:        return 0;
                    177: }
                    178:
                    179: /*
                    180:  * Read/Write a block from given place using the BIOS.
                    181:  */
                    182: static __inline int
                    183: CHS_rw(int rw, int dev, int cyl, int head, int sect, int nsect, void *buf)
                    184: {
                    185:        int rv;
                    186:
                    187:        rw = rw == F_READ ? 2 : 3;
                    188:        BIOS_regs.biosr_es = (u_int32_t)buf >> 4;
                    189:        __asm __volatile ("movb %b7, %h1\n\t"
                    190:            "movb %b6, %%dh\n\t"
                    191:            "andl $0xf, %4\n\t"
                    192:            /* cylinder; the highest 2 bits of cyl is in %cl */
                    193:            "xchgb %%ch, %%cl\n\t"
                    194:            "rorb  $2, %%cl\n\t"
                    195:            "orb %b5, %%cl\n\t"
                    196:            "inc %%cx\n\t"
                    197:            DOINT(0x13) "\n\t"
                    198:            "setc %b0"
                    199:            : "=a" (rv)
                    200:            : "0" (nsect), "d" (dev), "c" (cyl),
                    201:              "b" (buf), "m" (sect), "m" (head),
                    202:              "m" (rw)
                    203:            : "cc", "memory");
                    204:
                    205:        return ((rv & 0xff)? rv >> 8 : 0);
                    206: }
                    207:
                    208: static __inline int
                    209: EDD_rw(int rw, int dev, u_int64_t daddr, u_int32_t nblk, void *buf)
                    210: {
                    211:        int rv;
                    212:        volatile static struct EDD_CB cb;
                    213:
                    214:        /* Zero out reserved stuff */
                    215:        cb.edd_res1 = 0;
                    216:        cb.edd_res2 = 0;
                    217:
                    218:        /* Fill in parameters */
                    219:        cb.edd_len = sizeof(cb);
                    220:        cb.edd_nblk = nblk;
                    221:        cb.edd_seg = ((u_int32_t)buf >> 4) & 0xffff;
                    222:        cb.edd_off = (u_int32_t)buf & 0xf;
                    223:        cb.edd_daddr = daddr;
                    224:
                    225:        /* if offset/segment are zero, punt */
                    226:        if (!cb.edd_seg && !cb.edd_off)
                    227:                return 1;
                    228:
                    229:        /* Call extended read/write (with disk packet) */
                    230:        BIOS_regs.biosr_ds = (u_int32_t)&cb >> 4;
                    231:        __asm __volatile (DOINT(0x13) "; setc %b0" : "=a" (rv)
                    232:            : "0" ((rw == F_READ)? 0x4200: 0x4300),
                    233:              "d" (dev), "S" ((int) (&cb) & 0xf) : "%ecx", "cc");
                    234:        return ((rv & 0xff)? rv >> 8 : 0);
                    235: }
                    236:
                    237: /*
                    238:  * Read given sector, handling retry/errors/etc.
                    239:  */
                    240: int
                    241: biosd_io(int rw, bios_diskinfo_t *bd, daddr_t off, int nsect, void *buf)
                    242: {
                    243:        int dev = bd->bios_number;
                    244:        int j, error;
                    245:        void *bb;
                    246:        int bbsize = nsect * DEV_BSIZE;
                    247:
                    248:        if (bd->flags & BDI_EL_TORITO) {        /* It's a CD device */
                    249:                dev &= 0xff;                    /* Mask out this flag bit */
                    250:
                    251:                /*
                    252:                 * sys/lib/libsa/cd9600.c converts 2,048-byte CD sectors
                    253:                 * to DEV_BSIZE blocks before calling the device strategy
                    254:                 * routine.  However, the El Torito spec says that the
                    255:                 * BIOS will work in 2,048-byte sectors.  So shift back.
                    256:                 */
                    257:                off >>= (ISO_DEFAULT_BLOCK_SHIFT - DEV_BSHIFT);
                    258:                nsect >>= (ISO_DEFAULT_BLOCK_SHIFT - DEV_BSHIFT);
                    259:        }
                    260:
                    261:        /*
                    262:         * Use a bounce buffer to not cross 64k DMA boundary, and to
                    263:         * not access 1 MB or above.
                    264:         */
                    265:        if (((((u_int32_t)buf) & ~0xffff) !=
                    266:            (((u_int32_t)buf + bbsize) & ~0xffff)) ||
                    267:            (((u_int32_t)buf) >= 0x100000)) {
                    268:                /*
                    269:                 * XXX we believe that all the io is buffered
                    270:                 * by fs routines, so no big reads anyway
                    271:                 */
                    272:                bb = alloca(bbsize);
                    273:                if (rw != F_READ)
                    274:                        bcopy(buf, bb, bbsize);
                    275:        } else
                    276:                bb = buf;
                    277:
                    278:        /* Try to do operation up to 5 times */
                    279:        for (error = 1, j = 5; j-- && error; ) {
                    280:                /* CHS or LBA access? */
                    281:                if (bd->bios_edd != -1) {
                    282:                        error = EDD_rw(rw, dev, off, nsect, bb);
                    283:                } else {
                    284:                        int cyl, head, sect;
                    285:                        size_t i, n;
                    286:                        char *p = bb;
                    287:
                    288:                        /* Handle track boundaries */
                    289:                        for (error = i = 0; error == 0 && i < nsect;
                    290:                            i += n, off += n, p += n * DEV_BSIZE) {
                    291:
                    292:                                btochs(off, cyl, head, sect, bd->bios_heads,
                    293:                                    bd->bios_sectors);
                    294:
                    295:                                if ((sect + (nsect - i)) >= bd->bios_sectors)
                    296:                                        n = bd->bios_sectors - sect;
                    297:                                else
                    298:                                        n = nsect - i;
                    299:
                    300:                                error = CHS_rw(rw, dev, cyl, head, sect, n, p);
                    301:
                    302:                                /* ECC corrected */
                    303:                                if (error == 0x11)
                    304:                                        error = 0;
                    305:                        }
                    306:                }
                    307:                switch (error) {
                    308:                case 0x00:      /* No errors */
                    309:                case 0x11:      /* ECC corrected */
                    310:                        error = 0;
                    311:                        break;
                    312:
                    313:                default:        /* All other errors */
                    314: #ifdef BIOS_DEBUG
                    315:                        if (debug)
                    316:                                printf("\nBIOS error 0x%x (%s)\n",
                    317:                                    error, biosdisk_err(error));
                    318: #endif
                    319:                        biosdreset(dev);
                    320:                        break;
                    321:                }
                    322:        }
                    323:
                    324:        if (bb != buf && rw == F_READ)
                    325:                bcopy(bb, buf, bbsize);
                    326:
                    327: #ifdef BIOS_DEBUG
                    328:        if (debug) {
                    329:                if (error != 0)
                    330:                        printf("=0x%x(%s)", error, biosdisk_err(error));
                    331:                putchar('\n');
                    332:        }
                    333: #endif
                    334:
                    335:        return error;
                    336: }
                    337:
                    338: /*
                    339:  * Try to read the bsd label on the given BIOS device
                    340:  */
                    341: const char *
                    342: bios_getdisklabel(bios_diskinfo_t *bd, struct disklabel *label)
                    343: {
                    344:        daddr_t off = LABELSECTOR;
                    345:        char *buf;
                    346:        struct dos_mbr mbr;
                    347:        int error, i;
                    348:
                    349:        /* Sanity check */
                    350:        if (bd->bios_heads == 0 || bd->bios_sectors == 0)
                    351:                return "failed to read disklabel";
                    352:
                    353:        /* MBR is a harddisk thing */
                    354:        if (bd->bios_number & 0x80) {
                    355:                /* Read MBR */
                    356:                error = biosd_io(F_READ, bd, DOSBBSECTOR, 1, &mbr);
                    357:                if (error)
                    358:                        return (biosdisk_err(error));
                    359:
                    360:                /* check mbr signature */
                    361:                if (mbr.dmbr_sign != DOSMBR_SIGNATURE)
                    362:                        return "bad MBR signature\n";
                    363:
                    364:                /* Search for OpenBSD partition */
                    365:                for (off = 0, i = 0; off == 0 && i < NDOSPART; i++)
                    366:                        if (mbr.dmbr_parts[i].dp_typ == DOSPTYP_OPENBSD)
                    367:                                off = mbr.dmbr_parts[i].dp_start + LABELSECTOR;
                    368:                if (off == 0)
                    369:                        return "no OpenBSD partition\n";
                    370:        } else
                    371:                off = LABELSECTOR;
                    372:
                    373:        /* Load BSD disklabel */
                    374:        buf = alloca(DEV_BSIZE);
                    375: #ifdef BIOS_DEBUG
                    376:        if (debug)
                    377:                printf("loading disklabel @ %u\n", off);
                    378: #endif
                    379:        /* read disklabel */
                    380:        error = biosd_io(F_READ, bd, off, 1, buf);
                    381:
                    382:        if (error)
                    383:                return "failed to read disklabel";
                    384:
                    385:        /* Fill in disklabel */
                    386:        return (getdisklabel(buf, label));
                    387: }
                    388:
                    389: int
                    390: biosopen(struct open_file *f, ...)
                    391: {
                    392:        va_list ap;
                    393:        register char   *cp, **file;
                    394:        dev_t maj, unit, part;
                    395:        struct diskinfo *dip;
                    396:        int biosdev;
                    397:
                    398:        va_start(ap, f);
                    399:        cp = *(file = va_arg(ap, char **));
                    400:        va_end(ap);
                    401:
                    402: #ifdef BIOS_DEBUG
                    403:        if (debug)
                    404:                printf("%s\n", cp);
                    405: #endif
                    406:
                    407:        f->f_devdata = NULL;
                    408:        /* search for device specification */
                    409:        cp += 2;
                    410:        if (cp[2] != ':') {
                    411:                if (cp[3] != ':')
                    412:                        return ENOENT;
                    413:                else
                    414:                        cp++;
                    415:        }
                    416:
                    417:        for (maj = 0; maj < nbdevs && strncmp(*file, bdevs[maj], cp - *file); )
                    418:            maj++;
                    419:        if (maj >= nbdevs) {
                    420:                printf("Unknown device: ");
                    421:                for (cp = *file; *cp != ':'; cp++)
                    422:                        putchar(*cp);
                    423:                putchar('\n');
                    424:                return EADAPT;
                    425:        }
                    426:
                    427:        /* get unit */
                    428:        if ('0' <= *cp && *cp <= '9')
                    429:                unit = *cp++ - '0';
                    430:        else {
                    431:                printf("Bad unit number\n");
                    432:                return EUNIT;
                    433:        }
                    434:        /* get partition */
                    435:        if ('a' <= *cp && *cp <= 'p')
                    436:                part = *cp++ - 'a';
                    437:        else {
                    438:                printf("Bad partition id\n");
                    439:                return EPART;
                    440:        }
                    441:
                    442:        cp++;   /* skip ':' */
                    443:        if (*cp != 0)
                    444:                *file = cp;
                    445:        else
                    446:                f->f_flags |= F_RAW;
                    447:
                    448:        biosdev = unit;
                    449:        switch (maj) {
                    450:        case 0:  /* wd */
                    451:        case 4:  /* sd */
                    452:        case 17: /* hd */
                    453:                biosdev |= 0x80;
                    454:                break;
                    455:        case 2:  /* fd */
                    456:                break;
                    457:        case 6:  /* cd */
                    458:                biosdev = bios_bootdev & 0xff;
                    459:                break;
                    460:        default:
                    461:                return ENXIO;
                    462:        }
                    463:
                    464:        /* Find device */
                    465:        bootdev_dip = dip = dklookup(biosdev);
                    466:
                    467:        /* Fix up bootdev */
                    468:        { dev_t bsd_dev;
                    469:                bsd_dev = dip->bios_info.bsd_dev;
                    470:                dip->bsddev = MAKEBOOTDEV(B_TYPE(bsd_dev), B_ADAPTOR(bsd_dev),
                    471:                    B_CONTROLLER(bsd_dev), unit, part);
                    472:                dip->bootdev = MAKEBOOTDEV(B_TYPE(bsd_dev), B_ADAPTOR(bsd_dev),
                    473:                    B_CONTROLLER(bsd_dev), B_UNIT(bsd_dev), part);
                    474:        }
                    475:
                    476: #if 0
                    477:        dip->bios_info.bsd_dev = dip->bootdev;
                    478:        bootdev = dip->bootdev;
                    479: #endif
                    480:
                    481: #ifdef BIOS_DEBUG
                    482:        if (debug) {
                    483:                printf("BIOS geometry: heads=%u, s/t=%u; EDD=%d\n",
                    484:                    dip->bios_info.bios_heads, dip->bios_info.bios_sectors,
                    485:                    dip->bios_info.bios_edd);
                    486:        }
                    487: #endif
                    488:
                    489:        /* Try for disklabel again (might be removable media) */
                    490:        if (dip->bios_info.flags & BDI_BADLABEL){
                    491:                const char *st = bios_getdisklabel(&dip->bios_info,
                    492:                    &dip->disklabel);
                    493: #ifdef BIOS_DEBUG
                    494:                if (debug && st)
                    495:                        printf("%s\n", st);
                    496: #endif
                    497:                if (!st) {
                    498:                        dip->bios_info.flags &= ~BDI_BADLABEL;
                    499:                        dip->bios_info.flags |= BDI_GOODLABEL;
                    500:                } else
                    501:                        return ERDLAB;
                    502:        }
                    503:
                    504:        f->f_devdata = dip;
                    505:
                    506:        return 0;
                    507: }
                    508:
                    509: const u_char bidos_errs[] =
                    510: /* ignored     "\x00" "successful completion\0" */
                    511:                "\x01" "invalid function/parameter\0"
                    512:                "\x02" "address mark not found\0"
                    513:                "\x03" "write-protected\0"
                    514:                "\x04" "sector not found\0"
                    515:                "\x05" "reset failed\0"
                    516:                "\x06" "disk changed\0"
                    517:                "\x07" "drive parameter activity failed\0"
                    518:                "\x08" "DMA overrun\0"
                    519:                "\x09" "data boundary error\0"
                    520:                "\x0A" "bad sector detected\0"
                    521:                "\x0B" "bad track detected\0"
                    522:                "\x0C" "invalid media\0"
                    523:                "\x0E" "control data address mark detected\0"
                    524:                "\x0F" "DMA arbitration level out of range\0"
                    525:                "\x10" "uncorrectable CRC or ECC error on read\0"
                    526: /* ignored     "\x11" "data ECC corrected\0" */
                    527:                "\x20" "controller failure\0"
                    528:                "\x31" "no media in drive\0"
                    529:                "\x32" "incorrect drive type in CMOS\0"
                    530:                "\x40" "seek failed\0"
                    531:                "\x80" "operation timed out\0"
                    532:                "\xAA" "drive not ready\0"
                    533:                "\xB0" "volume not locked in drive\0"
                    534:                "\xB1" "volume locked in drive\0"
                    535:                "\xB2" "volume not removable\0"
                    536:                "\xB3" "volume in use\0"
                    537:                "\xB4" "lock count exceeded\0"
                    538:                "\xB5" "valid eject request failed\0"
                    539:                "\xBB" "undefined error\0"
                    540:                "\xCC" "write fault\0"
                    541:                "\xE0" "status register error\0"
                    542:                "\xFF" "sense operation failed\0"
                    543:                "\x00" "\0";
                    544:
                    545: static const char *
                    546: biosdisk_err(u_int error)
                    547: {
                    548:        register const u_char *p = bidos_errs;
                    549:
                    550:        while (*p && *p != error)
                    551:                while (*p++);
                    552:
                    553:        return ++p;
                    554: }
                    555:
                    556: const struct biosdisk_errors {
                    557:        u_char error;
                    558:        u_char errno;
                    559: } tab[] = {
                    560:        { 0x01, EINVAL },
                    561:        { 0x03, EROFS },
                    562:        { 0x08, EINVAL },
                    563:        { 0x09, EINVAL },
                    564:        { 0x0A, EBSE },
                    565:        { 0x0B, EBSE },
                    566:        { 0x0C, ENXIO },
                    567:        { 0x0D, EINVAL },
                    568:        { 0x10, EECC },
                    569:        { 0x20, EHER },
                    570:        { 0x31, ENXIO },
                    571:        { 0x32, ENXIO },
                    572:        { 0x00, EIO }
                    573: };
                    574:
                    575: static int
                    576: biosdisk_errno(u_int error)
                    577: {
                    578:        register const struct biosdisk_errors *p;
                    579:
                    580:        if (error == 0)
                    581:                return 0;
                    582:
                    583:        for (p = tab; p->error && p->error != error; p++);
                    584:
                    585:        return p->errno;
                    586: }
                    587:
                    588: int
                    589: biosstrategy(void *devdata, int rw, daddr_t blk, size_t size, void *buf,
                    590:     size_t *rsize)
                    591: {
                    592:        struct diskinfo *dip = (struct diskinfo *)devdata;
                    593:        bios_diskinfo_t *bd = &dip->bios_info;
                    594:        u_int8_t error = 0;
                    595:        size_t nsect;
                    596:
                    597:        nsect = (size + DEV_BSIZE-1) / DEV_BSIZE;
                    598:        if (rsize != NULL)
                    599:                blk += dip->disklabel.
                    600:                        d_partitions[B_PARTITION(dip->bsddev)].p_offset;
                    601:
                    602:        /* Read all, sub-functions handle track boundaries */
                    603:        error = biosd_io(rw, bd, blk, nsect, buf);
                    604:
                    605: #ifdef BIOS_DEBUG
                    606:        if (debug) {
                    607:                if (error != 0)
                    608:                        printf("=0x%x(%s)", error, biosdisk_err(error));
                    609:                putchar('\n');
                    610:        }
                    611: #endif
                    612:
                    613:        if (rsize != NULL)
                    614:                *rsize = nsect * DEV_BSIZE;
                    615:
                    616:        return (biosdisk_errno(error));
                    617: }
                    618:
                    619: int
                    620: biosclose(struct open_file *f)
                    621: {
                    622:        f->f_devdata = NULL;
                    623:
                    624:        return 0;
                    625: }
                    626:
                    627: int
                    628: biosioctl(struct open_file *f, u_long cmd, void *data)
                    629: {
                    630:        return 0;
                    631: }

CVSweb