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

Annotation of sys/arch/mvmeppc/stand/libsa/bugdev.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: bugdev.c,v 1.4 2006/10/12 12:14:17 krw Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1993 Paul Kranenburg
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *      This product includes software developed by Paul Kranenburg.
        !            18:  * 4. The name of the author may not be used to endorse or promote products
        !            19:  *    derived from this software without specific prior written permission
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: #include <sys/param.h>
        !            34: #include <sys/disklabel.h>
        !            35: #include <machine/prom.h>
        !            36:
        !            37: #include <stand.h>
        !            38: #include <ufs.h>
        !            39: #include "rawfs.h"
        !            40: #include "tftpfs.h"
        !            41:
        !            42: #include "libsa.h"
        !            43:
        !            44: int errno;
        !            45: int bootdev_type = BUGDEV_DISK;
        !            46:
        !            47: #if 1
        !            48: #define md_swap_long(x) ( (((x) >> 24) & 0xff) | (((x) >> 8 ) & 0xff00) | \
        !            49:                        (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000))
        !            50: #else
        !            51: #define md_swap_long(x) (x)
        !            52: #endif
        !            53:
        !            54: struct bugdev_softc {
        !            55:        int     fd;     /* Prom file descriptor */
        !            56:        u_int   pnum;   /* Partition number */
        !            57:        u_int   poff;   /* Partition offset */
        !            58:        u_int   psize;  /* Partition size */
        !            59:        short   clun;
        !            60:        short   dlun;
        !            61: } bugdev_softc[1];
        !            62:
        !            63: extern struct fs_ops ufs_file_system;
        !            64: extern struct fs_ops tftp_file_system;
        !            65: extern struct fs_ops raw_file_system;
        !            66:
        !            67: struct fs_ops file_system[1];
        !            68:
        !            69: struct mvmeprom_dskio tape_ioreq;
        !            70:
        !            71: #ifdef BUG_DEBUG
        !            72: unsigned io = 0, mem = 0;
        !            73: #define PCI_BASE 0x80000000
        !            74: #define CFC *(unsigned *)(PCI_BASE + 0xcfc)
        !            75: #define CF8 *(unsigned *)(PCI_BASE + 0xcf8)
        !            76: #define BUS_SHIFT 16
        !            77: #define DEVICE_SHIFT 11
        !            78: #define FNC_SHIFT 8
        !            79:
        !            80: unsigned
        !            81: bugpci_make_tag(bus, dev, fnc)
        !            82:        int bus, dev, fnc;
        !            83: {
        !            84:        return (bus << BUS_SHIFT) | (dev << DEVICE_SHIFT) | (fnc << FNC_SHIFT);
        !            85: }
        !            86:
        !            87: static unsigned
        !            88: bugpci_gen_config_reg(tag, offset)
        !            89:        unsigned tag;
        !            90:        int offset;
        !            91: {
        !            92:        unsigned reg;
        !            93:
        !            94:        /* config mechanism #2, type 0
        !            95:        /* standard cf8/cfc config */
        !            96:        reg =  0x80000000 | tag  | offset;
        !            97:
        !            98:        return reg;
        !            99: }
        !           100:
        !           101: /*#define DEBUG_CONFIG */
        !           102: unsigned
        !           103: bugpci_conf_read(bus, dev, func, offset)
        !           104:        int bus, dev, func, offset;
        !           105: {
        !           106:
        !           107:        unsigned data;
        !           108:        unsigned reg, tag, xx;
        !           109:
        !           110:        if(offset & 3 || offset < 0 || offset >= 0x100) {
        !           111:                printf ("bugpci_conf_read: bad reg %x\n", offset);
        !           112:                return(~0);
        !           113:        }
        !           114:
        !           115:         tag = bugpci_make_tag(bus, dev, func);
        !           116:        reg = bugpci_gen_config_reg(tag, offset);
        !           117:        reg = md_swap_long(reg);
        !           118:        /* if invalid tag, return -1 */
        !           119:        if (reg == 0xffffffff) {
        !           120:                return 0xffffffff;
        !           121:        }
        !           122:
        !           123:        CF8 = reg;
        !           124:        xx = CF8;
        !           125:        data = CFC;
        !           126:        data = md_swap_long(data);
        !           127:
        !           128:        CF8 = 0;
        !           129:
        !           130:        return(data);
        !           131: }
        !           132:
        !           133: void
        !           134: bugpci_conf_write(bus, dev, func, offset, data)
        !           135:        int bus, dev, func, offset;
        !           136:        unsigned data;
        !           137: {
        !           138:        unsigned reg, tag, xx;
        !           139:
        !           140:         tag = bugpci_make_tag(bus, dev, func);
        !           141:        reg = bugpci_gen_config_reg(tag, offset);
        !           142:        reg = md_swap_long(reg);
        !           143:
        !           144:        /* if invalid tag, return ??? */
        !           145:        if (reg == 0xffffffff) {
        !           146:                return;
        !           147:        }
        !           148:
        !           149:        CF8 = reg;
        !           150:        xx = CF8;
        !           151:        data = md_swap_long(data);
        !           152:        CFC = data;
        !           153:        CF8 = 0;
        !           154:        xx = CF8;
        !           155: }
        !           156: #endif
        !           157:
        !           158: static u_long
        !           159: get_long(p)
        !           160:        const void *p;
        !           161: {
        !           162:        const unsigned char *cp = p;
        !           163:
        !           164:        return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
        !           165: }
        !           166:
        !           167: /*
        !           168:  * Find a valid disklabel.
        !           169:  */
        !           170: static int
        !           171: search_label(devp, off, buf, lp, off0)
        !           172:        void *devp;
        !           173:        u_long off;
        !           174:        char *buf;
        !           175:        struct disklabel *lp;
        !           176:        u_long off0;
        !           177: {
        !           178:        size_t read;
        !           179:        struct dos_partition *p;
        !           180:        int i;
        !           181:        u_long poff;
        !           182:        static int recursion;
        !           183:
        !           184:        if (dsk_strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
        !           185:            || read != DEV_BSIZE)
        !           186:                return ERDLAB;
        !           187:
        !           188:        if (buf[510] != 0x55 || buf[511] != 0xaa)
        !           189:                return ERDLAB;
        !           190:
        !           191:        if (recursion++ <= 1)
        !           192:                off0 += off;
        !           193:        for (p = (struct dos_partition *)(buf + DOSPARTOFF), i = 4;
        !           194:             --i >= 0; p++) {
        !           195:                if (p->dp_typ == DOSPTYP_OPENBSD) {
        !           196:                        poff = get_long(&p->dp_start) + off0;
        !           197:                        if (dsk_strategy(devp, F_READ, poff + LABELSECTOR,
        !           198:                                     DEV_BSIZE, buf, &read) == 0
        !           199:                            && read == DEV_BSIZE) {
        !           200:                                if (!getdisklabel(buf, lp)) {
        !           201:                                        recursion--;
        !           202:                                        return 0;
        !           203:                                }
        !           204:                        }
        !           205:                        if (dsk_strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
        !           206:                            || read != DEV_BSIZE) {
        !           207:                                recursion--;
        !           208:                                return ERDLAB;
        !           209:                        }
        !           210:                } else if (p->dp_typ == DOSPTYP_EXTEND) {
        !           211:                        poff = get_long(&p->dp_start);
        !           212:                        if (!search_label(devp, poff, buf, lp, off0)) {
        !           213:                                recursion--;
        !           214:                                return 0;
        !           215:                        }
        !           216:                        if (dsk_strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
        !           217:                            || read != DEV_BSIZE) {
        !           218:                                recursion--;
        !           219:                                return ERDLAB;
        !           220:                        }
        !           221:                }
        !           222:        }
        !           223:        recursion--;
        !           224:        return ERDLAB;
        !           225: }
        !           226:
        !           227: int dsk_read_disklabel(devp)
        !           228:        void *devp;
        !           229: {
        !           230:        static  char iobuf[MAXBSIZE];
        !           231:        struct disklabel label;
        !           232:        int error = 0;
        !           233:        int i;
        !           234:
        !           235:        register struct bugdev_softc *pp = (struct bugdev_softc *)devp;
        !           236:
        !           237: #ifdef DEBUG
        !           238:        printf("dsk_open:\n");
        !           239: #endif
        !           240:        /* First try to find a disklabel without MBR partitions */
        !           241:        if (dsk_strategy(pp, F_READ, LABELSECTOR, DEV_BSIZE, iobuf, &i) != 0
        !           242:            || i != DEV_BSIZE
        !           243:            || getdisklabel(iobuf, &label)) {
        !           244:                /* Else try MBR partitions */
        !           245:                error = search_label(pp, 0, iobuf, &label, 0);
        !           246:                if (error && error != ERDLAB)
        !           247:                        return (error);
        !           248:        }
        !           249:        if (error == ERDLAB) {
        !           250:                if (pp->pnum)
        !           251:                        /* User specified a partition, but there is none */
        !           252:                        return (error);
        !           253:                /* No, label, just use complete disk */
        !           254:                pp->poff = 0;
        !           255:        } else {
        !           256:                pp->poff = label.d_partitions[pp->pnum].p_offset;
        !           257:                 pp->psize = label.d_partitions[pp->pnum].p_size;
        !           258:        }
        !           259:        return(0);
        !           260: }
        !           261:
        !           262:
        !           263: int
        !           264: devopen(f, fname, file)
        !           265:        struct open_file *f;
        !           266:        const char *fname;
        !           267:        char **file;
        !           268: {
        !           269:        register struct bugdev_softc *pp = &bugdev_softc[0];
        !           270:        int     error;
        !           271:        char    *dev, *cp;
        !           272:
        !           273:        pp->clun = (short)bugargs.ctrl_lun;
        !           274:        pp->dlun =  (short)bugargs.dev_lun;
        !           275:        pp->poff = 0;
        !           276:        pp->psize = 0;
        !           277:        pp->fd = 0;
        !           278:        pp->pnum = 0;
        !           279:
        !           280:        f->f_devdata = (void *)pp;
        !           281:
        !           282:        switch (bootdev_type) {
        !           283:        case BUGDEV_DISK:
        !           284:                dev = bugargs.arg_start;
        !           285:                /*
        !           286:                 * Extract partition # from boot device string.
        !           287:                 */
        !           288:                for (cp = dev; *cp; cp++) /* void */;
        !           289:                while (*cp != '/' && cp > dev) {
        !           290:                        if (*cp == ':')
        !           291:                                pp->pnum = *(cp+1) - 'a';
        !           292:                        --cp;
        !           293:                }
        !           294:
        !           295:                error = dsk_read_disklabel(pp);
        !           296:                if (error)
        !           297:                        return(error);
        !           298:
        !           299:                bcopy(&ufs_file_system, file_system, sizeof file_system[0]);
        !           300:                break;
        !           301:
        !           302:        case BUGDEV_NET:
        !           303:                bcopy(&tftp_file_system, file_system, sizeof file_system[0]);
        !           304:                break;
        !           305:
        !           306:        case BUGDEV_TAPE:
        !           307:                bcopy(&raw_file_system, file_system, sizeof file_system[0]);
        !           308:                break;
        !           309:        }
        !           310:
        !           311:        f->f_dev = &devsw[bootdev_type];
        !           312:        nfsys = 1;
        !           313:        *file = (char *)fname;
        !           314:        return (0);
        !           315: }
        !           316:
        !           317: /* silly block scale factor */
        !           318: #define BUG_BLOCK_SIZE 256
        !           319: #define BUG_SCALE (512/BUG_BLOCK_SIZE)
        !           320: int
        !           321: dsk_strategy(devdata, func, dblk, size, buf, rsize)
        !           322:        void *devdata;
        !           323:        int func;
        !           324:        daddr_t dblk;
        !           325:        size_t size;
        !           326:        void *buf;
        !           327:        size_t *rsize;
        !           328: {
        !           329:        struct mvmeprom_dskio dio;
        !           330:        register struct bugdev_softc *pp = (struct bugdev_softc *)devdata;
        !           331:        daddr_t blk = dblk + pp->poff;
        !           332:
        !           333:        twiddle();
        !           334:
        !           335:        dio.ctrl_lun = pp->clun;
        !           336:        dio.dev_lun = pp->dlun;
        !           337:        dio.status = 0;
        !           338:        dio.pbuffer = buf;
        !           339:        dio.blk_num = blk * BUG_SCALE;
        !           340:        dio.blk_cnt = size / BUG_BLOCK_SIZE; /* assumed size in bytes */
        !           341:        dio.flag = 0;
        !           342:        dio.addr_mod = 0;
        !           343: #ifdef DEBUG
        !           344:        printf("dsk_strategy: size=%d blk=%d buf=%x\n", size, blk, buf);
        !           345:        printf("ctrl %d dev %d\n", dio.ctrl_lun, dio.dev_lun);
        !           346: #endif
        !           347:        mvmeprom_diskrd(&dio);
        !           348:
        !           349:        *rsize = dio.blk_cnt * BUG_BLOCK_SIZE;
        !           350: #ifdef DEBUG
        !           351: printf("rsize %d status %x\n", *rsize, dio.status);
        !           352: #endif
        !           353:
        !           354:        if (dio.status)
        !           355:                return (EIO);
        !           356:        return (0);
        !           357: }
        !           358:
        !           359: int
        !           360: dsk_open(f)
        !           361:        struct open_file *f;
        !           362: {
        !           363: #ifdef DEBUG
        !           364:        register struct bugdev_softc *pp = (struct bugdev_softc *)f->f_devdata;
        !           365:        printf("dsk_open:\n");
        !           366:        printf("using mvmebug ctrl %d dev %d\n",
        !           367:                pp->clun, pp->dlun);
        !           368: #endif
        !           369:        return (0);
        !           370: }
        !           371:
        !           372: int
        !           373: dsk_close(f)
        !           374:        struct open_file *f;
        !           375: {
        !           376:        return (EIO);
        !           377: }
        !           378:
        !           379: int
        !           380: dsk_ioctl(f, cmd, data)
        !           381:        struct open_file *f;
        !           382:        u_long cmd;
        !           383:        void *data;
        !           384: {
        !           385:        return (EIO);
        !           386: }
        !           387:
        !           388: #define NFR_TIMEOUT    5
        !           389: /* netboot stuff */
        !           390: int
        !           391: net_strategy(devdata, func, nblk, size, buf, rsize)
        !           392:        void *devdata;
        !           393:        int func;
        !           394:        daddr_t nblk;
        !           395:        size_t size;
        !           396:        void *buf;
        !           397:        size_t *rsize;
        !           398: {
        !           399:        int attempts = 0;
        !           400:    struct mvmeprom_netfread nfr;
        !           401:        register struct bugdev_softc *pp = (struct bugdev_softc *)devdata;
        !           402:
        !           403: retry:
        !           404:
        !           405:    attempts+=1;
        !           406:
        !           407:    nfr.clun = pp->clun;
        !           408:        nfr.dlun = pp->dlun;
        !           409:        nfr.status = 0;
        !           410:        nfr.addr = buf;
        !           411:        nfr.bytes = 0;
        !           412:        nfr.blk = nblk;
        !           413:        nfr.timeout = NFR_TIMEOUT;
        !           414: #ifdef DEBUG
        !           415:        printf("net_strategy: size=%d blk=%d buf=%x\n", size, nblk, buf);
        !           416:        printf("ctrl %d dev %d\n", nfr.clun, nfr.dlun);
        !           417: #endif
        !           418:        mvmeprom_netfread(&nfr);
        !           419:
        !           420: #ifdef BUG_DEBUG
        !           421:        io = bugpci_conf_read(0, 14, 0, 0x10) & ~0xf;
        !           422:        mem = bugpci_conf_read(0, 14, 0, 0x14) & ~0xf;
        !           423:
        !           424:        printf(" IO @ %x\n", io);
        !           425:        printf("MEM @ %x\n", mem);
        !           426:
        !           427: #define PRINT_REG(regname, x) printf("%s = 0x%x\n", regname, \
        !           428:            md_swap_long(*(unsigned *)(io + x)))
        !           429:
        !           430:         PRINT_REG("CSR0", 0x00);
        !           431:         PRINT_REG("CSR1", 0x08);
        !           432:         PRINT_REG("CSR2", 0x10);
        !           433:         PRINT_REG("CSR3", 0x18);
        !           434:         PRINT_REG("CSR4", 0x20);
        !           435:         PRINT_REG("CSR5", 0x28);
        !           436:         PRINT_REG("CSR6", 0x30);
        !           437:         PRINT_REG("CSR7", 0x38);
        !           438:         PRINT_REG("CSR8", 0x40);
        !           439:         PRINT_REG("CSR9", 0x48);
        !           440:         PRINT_REG("CSR10", 0x50);
        !           441:         PRINT_REG("CSR11", 0x58);
        !           442:         PRINT_REG("CSR12", 0x60);
        !           443:         PRINT_REG("CSR13", 0x68);
        !           444:         PRINT_REG("CSR14", 0x70);
        !           445:         PRINT_REG("CSR15", 0x78);
        !           446: #endif
        !           447:        if (rsize) {
        !           448:                *rsize = nfr.bytes;
        !           449:        }
        !           450: #ifdef DEBUG
        !           451:        printf("rsize %d status %x\n", *rsize, nfr.status);
        !           452: #endif
        !           453:
        !           454:        if (nfr.status)
        !           455:       if (attempts < 10)
        !           456:          goto retry;
        !           457:       else
        !           458:                   return (EIO);
        !           459:        return (0);
        !           460: }
        !           461:
        !           462: int
        !           463: net_open(struct open_file *f, ...)
        !           464: {
        !           465:        va_list ap;
        !           466:        struct mvmeprom_netfopen nfo;
        !           467:         register struct bugdev_softc *pp = (struct bugdev_softc *)f->f_devdata;
        !           468:        char *filename;
        !           469:        short nfoerr = 0;
        !           470:        va_start(ap, f);
        !           471:        filename = va_arg(ap, char *);
        !           472:        va_end(ap);
        !           473:
        !           474: #ifdef DEBUG
        !           475:        printf("net_open: using mvmebug ctrl %d dev %d, filename: %s\n",
        !           476:            pp->clun, pp->dlun, filename);
        !           477: #endif
        !           478:        nfo.clun = pp->clun;
        !           479:        nfo.dlun = pp->dlun;
        !           480:        nfo.status = 0;
        !           481:        strlcpy(nfo.filename, filename, sizeof nfo.filename);
        !           482:        /* .NETFOPN syscall */
        !           483:        mvmeprom_netfopen(&nfo);
        !           484:
        !           485: #ifdef DEBUG
        !           486:        if (nfo.status) {
        !           487:                nfoerr = nfo.status;
        !           488:                printf("net_open: ci err = 0x%x, cd err = 0x%x\n",
        !           489:                    ((nfoerr >> 8) & 0x0F), (nfoerr & 0x0F));
        !           490:        }
        !           491: #endif
        !           492:        return (nfo.status);
        !           493: }
        !           494:
        !           495: int
        !           496: net_close(f)
        !           497:        struct open_file *f;
        !           498: {
        !           499:        return (EIO);
        !           500: }
        !           501:
        !           502: int
        !           503: net_ioctl(f, cmd, data)
        !           504:        struct open_file *f;
        !           505:        u_long cmd;
        !           506:        void *data;
        !           507: {
        !           508:        return (EIO);
        !           509: }
        !           510:
        !           511: int
        !           512: tape_open(struct open_file *f, ...)
        !           513: {
        !           514:        va_list ap;
        !           515:        int     error = 0;
        !           516:        int     part;
        !           517:        struct mvmeprom_dskio *ti;
        !           518:        char *fname;            /* partition number, i.e. "1" */
        !           519:
        !           520:        va_start(ap, f);
        !           521:        fname = va_arg(ap, char *);
        !           522:        va_end(ap);
        !           523:
        !           524:        /*
        !           525:         * Set the tape segment number to the one indicated
        !           526:         * by the single digit fname passed in above.
        !           527:         */
        !           528:        if ((fname[0] < '0') && (fname[0] > '9')) {
        !           529:                return ENOENT;
        !           530:        }
        !           531:        part = fname[0] - '0';
        !           532:        fname = NULL;
        !           533:
        !           534:        /*
        !           535:         * Setup our part of the saioreq.
        !           536:         * (determines what gets opened)
        !           537:         */
        !           538:        ti = &tape_ioreq;
        !           539:        bzero((caddr_t)ti, sizeof(*ti));
        !           540:
        !           541:        ti->ctrl_lun = bugargs.ctrl_lun;
        !           542:        ti->dev_lun = bugargs.dev_lun;
        !           543:        ti->status = 0;
        !           544:        ti->pbuffer = NULL;
        !           545:        ti->blk_num = part;
        !           546:        ti->blk_cnt = 0;
        !           547:        ti->flag = 0;
        !           548:        ti->addr_mod = 0;
        !           549:
        !           550:        f->f_devdata = ti;
        !           551:
        !           552:        return (0);
        !           553: }
        !           554:
        !           555: int
        !           556: tape_close(f)
        !           557:        struct open_file *f;
        !           558: {
        !           559:        struct mvmeprom_dskio *ti;
        !           560:
        !           561:
        !           562:        ti = f->f_devdata;
        !           563:        f->f_devdata = NULL;
        !           564:        return 0;
        !           565: }
        !           566:
        !           567: #define MVMEPROM_SCALE (512/MVMEPROM_BLOCK_SIZE)
        !           568:
        !           569: int
        !           570: tape_strategy(devdata, flag, dblk, size, buf, rsize)
        !           571:        void    *devdata;
        !           572:        int     flag;
        !           573:        daddr_t dblk;
        !           574:        size_t  size;
        !           575:        void    *buf;
        !           576:        size_t  *rsize;
        !           577: {
        !           578:        struct mvmeprom_dskio *ti;
        !           579:        int ret;
        !           580:
        !           581:        ti = devdata;
        !           582:
        !           583:        if (flag != F_READ)
        !           584:                return(EROFS);
        !           585:
        !           586:        ti->status = 0;
        !           587:        ti->pbuffer = buf;
        !           588:        /* don't change block #, set in open */
        !           589:        ti->blk_cnt = size / (512 / MVMEPROM_SCALE);
        !           590:
        !           591:        ret = mvmeprom_diskrd(ti);
        !           592:
        !           593:        if (ret != 0)
        !           594:                return (EIO);
        !           595:
        !           596:        *rsize = (ti->blk_cnt / MVMEPROM_SCALE) * 512;
        !           597:        ti->flag |= IGNORE_FILENUM; /* ignore next time */
        !           598:
        !           599:        return (0);
        !           600: }
        !           601:
        !           602: int
        !           603: tape_ioctl(f, cmd, data)
        !           604:        struct open_file *f;
        !           605:        u_long cmd;
        !           606:        void *data;
        !           607: {
        !           608:        return EIO;
        !           609: }
        !           610:
        !           611:

CVSweb