[BACK]Return to dk.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / dkwedge

Annotation of src/sys/dev/dkwedge/dk.c, Revision 1.3

1.3     ! thorpej     1: /*     $NetBSD: dk.c,v 1.2 2004/10/15 04:42:09 thorpej Exp $   */
1.1       thorpej     2:
                      3: /*-
                      4:  * Copyright (c) 2004 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Jason R. Thorpe.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the NetBSD
                     21:  *     Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
                     38:
                     39: #include <sys/cdefs.h>
1.3     ! thorpej    40: __KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.2 2004/10/15 04:42:09 thorpej Exp $");
1.1       thorpej    41:
                     42: #include "opt_dkwedge.h"
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/proc.h>
                     47: #include <sys/errno.h>
                     48: #include <sys/pool.h>
                     49: #include <sys/ioctl.h>
                     50: #include <sys/disklabel.h>
                     51: #include <sys/disk.h>
                     52: #include <sys/fcntl.h>
                     53: #include <sys/vnode.h>
1.3     ! thorpej    54: #include <sys/stat.h>
1.1       thorpej    55: #include <sys/conf.h>
                     56: #include <sys/callout.h>
                     57: #include <sys/kernel.h>
                     58: #include <sys/lock.h>
                     59: #include <sys/malloc.h>
1.2       thorpej    60: #include <sys/device.h>
1.1       thorpej    61:
                     62: #include <miscfs/specfs/specdev.h>
                     63:
                     64: MALLOC_DEFINE(M_DKWEDGE, "dkwedge", "Disk wedge structures");
                     65:
                     66: typedef enum {
                     67:        DKW_STATE_LARVAL        = 0,
                     68:        DKW_STATE_RUNNING       = 1,
                     69:        DKW_STATE_DYING         = 2,
                     70:        DKW_STATE_DEAD          = 666
                     71: } dkwedge_state_t;
                     72:
                     73: struct dkwedge_softc {
1.2       thorpej    74:        struct device   *sc_dev;        /* pointer to our pseudo-device */
                     75:        struct cfdata   sc_cfdata;      /* our cfdata structure */
1.1       thorpej    76:        uint8_t         sc_wname[128];  /* wedge name (Unicode, UTF-8) */
                     77:
                     78:        dkwedge_state_t sc_state;       /* state this wedge is in */
                     79:
                     80:        struct disk     *sc_parent;     /* parent disk */
                     81:        daddr_t         sc_offset;      /* LBA offset of wedge in parent */
                     82:        uint64_t        sc_size;        /* size of wedge in blocks */
                     83:        char            sc_ptype[32];   /* partition type */
                     84:        dev_t           sc_pdev;        /* cached parent's dev_t */
                     85:                                        /* link on parent's wedge list */
                     86:        LIST_ENTRY(dkwedge_softc) sc_plink;
                     87:
                     88:        struct disk     sc_dk;          /* our own disk structure */
                     89:        struct bufq_state sc_bufq;      /* buffer queue */
                     90:        struct callout  sc_restart_ch;  /* callout to restart I/O */
                     91:
                     92:        u_int           sc_iopend;      /* I/Os pending */
                     93:        int             sc_flags;       /* flags (splbio) */
                     94: };
                     95:
                     96: #define        DK_F_WAIT_DRAIN         0x0001  /* waiting for I/O to drain */
                     97:
                     98: static void    dkstart(struct dkwedge_softc *);
                     99: static void    dkiodone(struct buf *);
                    100: static void    dkrestart(void *);
                    101:
                    102: static dev_type_open(dkopen);
                    103: static dev_type_close(dkclose);
                    104: static dev_type_read(dkread);
                    105: static dev_type_write(dkwrite);
                    106: static dev_type_ioctl(dkioctl);
                    107: static dev_type_strategy(dkstrategy);
                    108: static dev_type_dump(dkdump);
                    109: static dev_type_size(dksize);
                    110:
                    111: const struct bdevsw dk_bdevsw = {
                    112:        dkopen, dkclose, dkstrategy, dkioctl, dkdump, dksize, D_DISK
                    113: };
                    114:
                    115: const struct cdevsw dk_cdevsw = {
                    116:        dkopen, dkclose, dkread, dkwrite, dkioctl,
                    117:            nostop, notty, nopoll, nommap, nokqfilter, D_DISK
                    118: };
                    119:
                    120: static struct dkwedge_softc **dkwedges;
                    121: static u_int ndkwedges;
                    122: static struct lock dkwedges_lock = LOCK_INITIALIZER(PRIBIO, "dkwgs", 0, 0);
                    123:
                    124: static LIST_HEAD(, dkwedge_discovery_method) dkwedge_discovery_methods;
                    125: static int dkwedge_discovery_methods_initialized;
                    126: static struct lock dkwedge_discovery_methods_lock =
                    127:     LOCK_INITIALIZER(PRIBIO, "dkddm", 0, 0);
                    128:
                    129: /*
1.2       thorpej   130:  * dkwedge_match:
                    131:  *
                    132:  *     Autoconfiguration match function for pseudo-device glue.
                    133:  */
                    134: static int
                    135: dkwedge_match(struct device *parent, struct cfdata *match, void *aux)
                    136: {
                    137:
                    138:        /* Pseudo-device; always present. */
                    139:        return (1);
                    140: }
                    141:
                    142: /*
                    143:  * dkwedge_attach:
                    144:  *
                    145:  *     Autoconfiguration attach function for pseudo-device glue.
                    146:  */
                    147: static void
                    148: dkwedge_attach(struct device *parent, struct device *self, void *aux)
                    149: {
                    150:
                    151:        /* Nothing to do. */
                    152: }
                    153:
                    154: /*
                    155:  * dkwedge_detach:
                    156:  *
                    157:  *     Autoconfiguration detach function for pseudo-device glue.
                    158:  */
                    159: static int
                    160: dkwedge_detach(struct device *self, int flags)
                    161: {
                    162:
                    163:        /* Always succeeds. */
                    164:        return (0);
                    165: }
                    166:
                    167: CFDRIVER_DECL(dk, DV_DISK, NULL);
                    168: CFATTACH_DECL(dk, sizeof(struct device),
                    169:              dkwedge_match, dkwedge_attach, dkwedge_detach, NULL);
                    170:
                    171: static int dkwedge_cfglue_initialized;
                    172: static struct simplelock dkwedge_cfglue_initialized_slock =
                    173:     SIMPLELOCK_INITIALIZER;
                    174:
                    175: static void
                    176: dkwedge_cfglue_init(void)
                    177: {
                    178:
                    179:        simple_lock(&dkwedge_cfglue_initialized_slock);
                    180:        if (dkwedge_cfglue_initialized == 0) {
                    181:                if (config_cfdriver_attach(&dk_cd) != 0)
                    182:                        panic("dkwedge: unable to attach cfdriver");
                    183:                if (config_cfattach_attach(dk_cd.cd_name, &dk_ca) != 0)
                    184:                        panic("dkwedge: unable to attach cfattach");
                    185:
                    186:                dkwedge_cfglue_initialized = 1;
                    187:        }
                    188:        simple_unlock(&dkwedge_cfglue_initialized_slock);
                    189: }
                    190:
                    191: /*
1.1       thorpej   192:  * dkwedge_wait_drain:
                    193:  *
                    194:  *     Wait for I/O on the wedge to drain.
                    195:  *     NOTE: Must be called at splbio()!
                    196:  */
                    197: static void
                    198: dkwedge_wait_drain(struct dkwedge_softc *sc)
                    199: {
                    200:
                    201:        while (sc->sc_iopend != 0) {
                    202:                sc->sc_flags |= DK_F_WAIT_DRAIN;
                    203:                (void) tsleep(&sc->sc_iopend, PRIBIO, "dkdrn", 0);
                    204:        }
                    205: }
                    206:
                    207: /*
                    208:  * dkwedge_compute_pdev:
                    209:  *
                    210:  *     Compute the parent disk's dev_t.
                    211:  */
                    212: static int
                    213: dkwedge_compute_pdev(const char *pname, dev_t *pdevp)
                    214: {
                    215:        const char *name, *cp;
                    216:        int punit, pmaj;
                    217:        char devname[16];
                    218:
                    219:        name = pname;
                    220:        if ((pmaj = devsw_name2blk(name, devname, sizeof(devname))) == -1)
                    221:                return (ENODEV);
                    222:
                    223:        name += strlen(devname);
                    224:        for (cp = name, punit = 0; *cp >= '0' && *cp <= '9'; cp++)
                    225:                punit = (punit * 10) + (*cp - '0');
                    226:        if (cp == name) {
                    227:                /* Invalid parent disk name. */
                    228:                return (ENODEV);
                    229:        }
                    230:
                    231:        *pdevp = MAKEDISKDEV(pmaj, punit, RAW_PART);
                    232:
                    233:        return (0);
                    234: }
                    235:
                    236: /*
                    237:  * dkwedge_array_expand:
                    238:  *
                    239:  *     Expand the dkwedges array.
                    240:  */
                    241: static void
                    242: dkwedge_array_expand(void)
                    243: {
                    244:        int newcnt = ndkwedges + 16;
                    245:        struct dkwedge_softc **newarray, **oldarray;
                    246:
                    247:        newarray = malloc(newcnt * sizeof(*newarray), M_DKWEDGE,
                    248:            M_WAITOK|M_ZERO);
                    249:        if ((oldarray = dkwedges) != NULL)
                    250:                memcpy(newarray, dkwedges, ndkwedges * sizeof(*newarray));
                    251:        dkwedges = newarray;
                    252:        ndkwedges = newcnt;
                    253:        if (oldarray != NULL)
                    254:                free(oldarray, M_DKWEDGE);
                    255: }
                    256:
                    257: /*
                    258:  * dkwedge_add:                [exported function]
                    259:  *
                    260:  *     Add a disk wedge based on the provided information.
                    261:  *
                    262:  *     The incoming dkw_devname[] is ignored, instead being
                    263:  *     filled in and returned to the caller.
                    264:  */
                    265: int
                    266: dkwedge_add(struct dkwedge_info *dkw)
                    267: {
                    268:        struct dkwedge_softc *sc, *lsc;
                    269:        struct disk *pdk;
                    270:        u_int unit;
                    271:        int error;
                    272:        dev_t pdev;
                    273:
1.2       thorpej   274:        if (dkwedge_cfglue_initialized == 0)
                    275:                dkwedge_cfglue_init();
                    276:
1.1       thorpej   277:        dkw->dkw_parent[sizeof(dkw->dkw_parent) - 1] = '\0';
                    278:        pdk = disk_find(dkw->dkw_parent);
                    279:        if (pdk == NULL)
                    280:                return (ENODEV);
                    281:
                    282:        error = dkwedge_compute_pdev(pdk->dk_name, &pdev);
                    283:        if (error)
                    284:                return (error);
                    285:
                    286:        if (dkw->dkw_offset < 0)
                    287:                return (EINVAL);
                    288:
                    289:        sc = malloc(sizeof(*sc), M_DKWEDGE, M_WAITOK|M_ZERO);
                    290:        sc->sc_state = DKW_STATE_LARVAL;
                    291:        sc->sc_parent = pdk;
                    292:        sc->sc_pdev = pdev;
                    293:        sc->sc_offset = dkw->dkw_offset;
                    294:        sc->sc_size = dkw->dkw_size;
                    295:
                    296:        memcpy(sc->sc_wname, dkw->dkw_wname, sizeof(sc->sc_wname));
                    297:        sc->sc_wname[sizeof(sc->sc_wname) - 1] = '\0';
                    298:
                    299:        memcpy(sc->sc_ptype, dkw->dkw_ptype, sizeof(sc->sc_ptype));
                    300:        sc->sc_ptype[sizeof(sc->sc_ptype) - 1] = '\0';
                    301:
                    302:        bufq_alloc(&sc->sc_bufq, BUFQ_FCFS);
                    303:
                    304:        callout_init(&sc->sc_restart_ch);
                    305:        callout_setfunc(&sc->sc_restart_ch, dkrestart, sc);
                    306:
                    307:        /*
                    308:         * Wedge will be added; increment the wedge count for the parent.
                    309:         * Only allow this to happend if RAW_PART is the only thing open.
                    310:         */
                    311:        (void) lockmgr(&pdk->dk_openlock, LK_EXCLUSIVE, NULL);
                    312:        if (pdk->dk_openmask & ~(1 << RAW_PART))
                    313:                error = EBUSY;
                    314:        else {
                    315:                /* Check for wedge overlap. */
                    316:                LIST_FOREACH(lsc, &pdk->dk_wedges, sc_plink) {
                    317:                        daddr_t lastblk = sc->sc_offset + sc->sc_size - 1;
                    318:                        daddr_t llastblk = lsc->sc_offset + lsc->sc_size - 1;
                    319:
                    320:                        if (sc->sc_offset >= lsc->sc_offset &&
                    321:                            sc->sc_offset <= llastblk) {
                    322:                                /* Overlaps the tail of the exsiting wedge. */
                    323:                                break;
                    324:                        }
                    325:                        if (lastblk >= lsc->sc_offset &&
                    326:                            lastblk <= llastblk) {
                    327:                                /* Overlaps the head of the existing wedge. */
                    328:                                break;
                    329:                        }
                    330:                }
                    331:                if (lsc != NULL)
                    332:                        error = EINVAL;
                    333:                else {
                    334:                        pdk->dk_nwedges++;
                    335:                        LIST_INSERT_HEAD(&pdk->dk_wedges, sc, sc_plink);
                    336:                }
                    337:        }
                    338:        (void) lockmgr(&pdk->dk_openlock, LK_RELEASE, NULL);
                    339:        if (error) {
                    340:                bufq_free(&sc->sc_bufq);
                    341:                free(sc, M_DKWEDGE);
                    342:                return (error);
                    343:        }
                    344:
1.2       thorpej   345:        /* Fill in our cfdata for the pseudo-device glue. */
                    346:        sc->sc_cfdata.cf_name = dk_cd.cd_name;
                    347:        sc->sc_cfdata.cf_atname = dk_ca.ca_name;
                    348:        /* sc->sc_cfdata.cf_unit set below */
                    349:        sc->sc_cfdata.cf_fstate = FSTATE_NOTFOUND;
                    350:
1.1       thorpej   351:        /* Insert the larval wedge into the array. */
                    352:        (void) lockmgr(&dkwedges_lock, LK_EXCLUSIVE, NULL);
                    353:        for (error = 0;;) {
                    354:                struct dkwedge_softc **scpp;
                    355:
                    356:                /*
                    357:                 * Check for a duplicate wname while searching for
                    358:                 * a slot.
                    359:                 */
                    360:                for (scpp = NULL, unit = 0; unit < ndkwedges; unit++) {
                    361:                        if (dkwedges[unit] == NULL) {
                    362:                                if (scpp == NULL) {
                    363:                                        scpp = &dkwedges[unit];
1.2       thorpej   364:                                        sc->sc_cfdata.cf_unit = unit;
1.1       thorpej   365:                                }
                    366:                        } else {
                    367:                                /* XXX Unicode. */
                    368:                                if (strcmp(dkwedges[unit]->sc_wname,
                    369:                                           sc->sc_wname) == 0) {
                    370:                                        error = EEXIST;
                    371:                                        break;
                    372:                                }
                    373:                        }
                    374:                }
                    375:                if (error)
                    376:                        break;
                    377:                KASSERT(unit == ndkwedges);
                    378:                if (scpp == NULL)
                    379:                        dkwedge_array_expand();
                    380:                else {
1.2       thorpej   381:                        KASSERT(scpp == &dkwedges[sc->sc_cfdata.cf_unit]);
1.1       thorpej   382:                        *scpp = sc;
                    383:                        break;
                    384:                }
                    385:        }
                    386:        (void) lockmgr(&dkwedges_lock, LK_RELEASE, NULL);
                    387:        if (error) {
                    388:                (void) lockmgr(&pdk->dk_openlock, LK_EXCLUSIVE, NULL);
                    389:                pdk->dk_nwedges--;
                    390:                LIST_REMOVE(sc, sc_plink);
                    391:                (void) lockmgr(&pdk->dk_openlock, LK_RELEASE, NULL);
                    392:
                    393:                bufq_free(&sc->sc_bufq);
                    394:                free(sc, M_DKWEDGE);
                    395:                return (error);
                    396:        }
                    397:
1.2       thorpej   398:        /*
                    399:         * Now that we know the unit #, attach a pseudo-device for
                    400:         * this wedge instance.  This will provide us with the
                    401:         * "struct device" necessary for glue to other parts of the
                    402:         * system.
                    403:         *
                    404:         * This should never fail, unless we're almost totally out of
                    405:         * memory.
                    406:         */
                    407:        if ((sc->sc_dev = config_attach_pseudo(&sc->sc_cfdata)) == NULL) {
                    408:                aprint_error("%s%u: unable to attach pseudo-device\n",
                    409:                    sc->sc_cfdata.cf_name, sc->sc_cfdata.cf_unit);
                    410:
                    411:                (void) lockmgr(&dkwedges_lock, LK_EXCLUSIVE, NULL);
                    412:                dkwedges[sc->sc_cfdata.cf_unit] = NULL;
                    413:                (void) lockmgr(&dkwedges_lock, LK_RELEASE, NULL);
                    414:
                    415:                (void) lockmgr(&pdk->dk_openlock, LK_EXCLUSIVE, NULL);
                    416:                pdk->dk_nwedges--;
                    417:                LIST_REMOVE(sc, sc_plink);
                    418:                (void) lockmgr(&pdk->dk_openlock, LK_RELEASE, NULL);
                    419:
                    420:                bufq_free(&sc->sc_bufq);
                    421:                free(sc, M_DKWEDGE);
                    422:                return (ENOMEM);
                    423:        }
                    424:        sc->sc_dk.dk_name = sc->sc_dev->dv_xname;
1.1       thorpej   425:
                    426:        /* Return the devname to the caller. */
1.2       thorpej   427:        strcpy(dkw->dkw_devname, sc->sc_dev->dv_xname);
1.1       thorpej   428:
                    429:        /*
                    430:         * XXX Really ought to make the disk_attach() and the changing
                    431:         * of state to RUNNING atomic.
                    432:         */
                    433:
                    434:        disk_attach(&sc->sc_dk);
                    435:
                    436:        /* Disk wedge is ready for use! */
                    437:        sc->sc_state = DKW_STATE_RUNNING;
                    438:
                    439:        /* Announce our arrival. */
1.2       thorpej   440:        aprint_normal("%s at %s: %s\n", sc->sc_dev->dv_xname, pdk->dk_name,
1.1       thorpej   441:            sc->sc_wname);      /* XXX Unicode */
                    442:        aprint_normal("%s: %"PRIu64" blocks at %"PRId64", type: %s\n",
1.2       thorpej   443:            sc->sc_dev->dv_xname, sc->sc_size, sc->sc_offset, sc->sc_ptype);
1.1       thorpej   444:
                    445:        return (0);
                    446: }
                    447:
                    448: /*
                    449:  * dkwedge_del:                [exported function]
                    450:  *
                    451:  *     Delete a disk wedge based on the provided information.
                    452:  *     NOTE: We look up the wedge based on the wedge devname,
                    453:  *     not wname.
                    454:  */
                    455: int
                    456: dkwedge_del(struct dkwedge_info *dkw)
                    457: {
                    458:        struct dkwedge_softc *sc = NULL;
                    459:        u_int unit;
                    460:        int bmaj, cmaj, i, mn, s;
                    461:
                    462:        /* Find our softc. */
                    463:        dkw->dkw_devname[sizeof(dkw->dkw_devname) - 1] = '\0';
                    464:        (void) lockmgr(&dkwedges_lock, LK_EXCLUSIVE, NULL);
                    465:        for (unit = 0; unit < ndkwedges; unit++) {
                    466:                if ((sc = dkwedges[unit]) != NULL &&
1.2       thorpej   467:                    strcmp(sc->sc_dev->dv_xname, dkw->dkw_devname) == 0 &&
1.1       thorpej   468:                    strcmp(sc->sc_parent->dk_name, dkw->dkw_parent) == 0) {
                    469:                        /* Mark the wedge as dying. */
                    470:                        sc->sc_state = DKW_STATE_DYING;
                    471:                        break;
                    472:                }
                    473:        }
                    474:        (void) lockmgr(&dkwedges_lock, LK_RELEASE, NULL);
                    475:        if (unit == ndkwedges)
                    476:                return (ESRCH);
                    477:
                    478:        KASSERT(sc != NULL);
                    479:
                    480:        /* Locate the wedge major numbers. */
                    481:        bmaj = bdevsw_lookup_major(&dk_bdevsw);
                    482:        cmaj = cdevsw_lookup_major(&dk_cdevsw);
                    483:
                    484:        /* Kill any pending restart. */
                    485:        callout_stop(&sc->sc_restart_ch);
                    486:
                    487:        /*
                    488:         * dkstart() will kill any queued buffers now that the
                    489:         * state of the wedge is not RUNNING.  Once we've done
                    490:         * that, wait for any other pending I/O to complete.
                    491:         */
                    492:        s = splbio();
                    493:        dkstart(sc);
                    494:        dkwedge_wait_drain(sc);
                    495:        splx(s);
                    496:
                    497:        /* Nuke the vnodes for any open instances. */
                    498:        for (i = 0; i < MAXPARTITIONS; i++) {
                    499:                mn = DISKMINOR(unit, i);
                    500:                vdevgone(bmaj, mn, mn, VBLK);
                    501:                vdevgone(cmaj, mn, mn, VCHR);
                    502:        }
                    503:
                    504:        /* Clean up the parent. */
1.3     ! thorpej   505:        (void) lockmgr(&sc->sc_dk.dk_openlock, LK_EXCLUSIVE, NULL);
1.1       thorpej   506:        (void) lockmgr(&sc->sc_parent->dk_rawlock, LK_EXCLUSIVE, NULL);
1.3     ! thorpej   507:        if (sc->sc_dk.dk_openmask) {
1.1       thorpej   508:                if (sc->sc_parent->dk_rawopens-- == 1) {
                    509:                        KASSERT(sc->sc_parent->dk_rawvp != NULL);
                    510:                        (void) vn_close(sc->sc_parent->dk_rawvp, FREAD | FWRITE,
                    511:                                        NOCRED, curproc);
                    512:                        sc->sc_parent->dk_rawvp = NULL;
                    513:                }
1.3     ! thorpej   514:                sc->sc_dk.dk_openmask = 0;
1.1       thorpej   515:        }
                    516:        (void) lockmgr(&sc->sc_parent->dk_rawlock, LK_RELEASE, NULL);
1.3     ! thorpej   517:        (void) lockmgr(&sc->sc_dk.dk_openlock, LK_RELEASE, NULL);
1.1       thorpej   518:
                    519:        /* Announce our departure. */
1.2       thorpej   520:        aprint_normal("%s at %s (%s) deleted\n", sc->sc_dev->dv_xname,
1.1       thorpej   521:            sc->sc_parent->dk_name,
                    522:            sc->sc_wname);      /* XXX Unicode */
                    523:
1.2       thorpej   524:        /* Delete our pseudo-device. */
                    525:        (void) config_detach(sc->sc_dev, DETACH_FORCE | DETACH_QUIET);
                    526:
1.1       thorpej   527:        (void) lockmgr(&sc->sc_parent->dk_openlock, LK_EXCLUSIVE, NULL);
                    528:        sc->sc_parent->dk_nwedges--;
                    529:        LIST_REMOVE(sc, sc_plink);
                    530:        (void) lockmgr(&sc->sc_parent->dk_openlock, LK_RELEASE, NULL);
                    531:
                    532:        /* Delete our buffer queue. */
                    533:        bufq_free(&sc->sc_bufq);
                    534:
                    535:        /* Detach from the disk list. */
                    536:        disk_detach(&sc->sc_dk);
                    537:
                    538:        /* Poof. */
                    539:        (void) lockmgr(&dkwedges_lock, LK_EXCLUSIVE, NULL);
                    540:        dkwedges[unit] = NULL;
                    541:        sc->sc_state = DKW_STATE_DEAD;
                    542:        (void) lockmgr(&dkwedges_lock, LK_RELEASE, NULL);
                    543:
                    544:        free(sc, M_DKWEDGE);
                    545:
                    546:        return (0);
                    547: }
                    548:
                    549: /*
                    550:  * dkwedge_delall:     [exported function]
                    551:  *
                    552:  *     Delete all of the wedges on the specified disk.  Used when
                    553:  *     a disk is being detached.
                    554:  */
                    555: void
                    556: dkwedge_delall(struct disk *pdk)
                    557: {
                    558:        struct dkwedge_info dkw;
                    559:        struct dkwedge_softc *sc;
                    560:
                    561:        for (;;) {
                    562:                (void) lockmgr(&pdk->dk_openlock, LK_EXCLUSIVE, NULL);
                    563:                if ((sc = LIST_FIRST(&pdk->dk_wedges)) == NULL) {
                    564:                        KASSERT(pdk->dk_nwedges == 0);
                    565:                        (void) lockmgr(&pdk->dk_openlock, LK_RELEASE, NULL);
                    566:                        return;
                    567:                }
                    568:                strcpy(dkw.dkw_parent, pdk->dk_name);
1.2       thorpej   569:                strcpy(dkw.dkw_devname, sc->sc_dev->dv_xname);
1.1       thorpej   570:                (void) lockmgr(&pdk->dk_openlock, LK_RELEASE, NULL);
                    571:                (void) dkwedge_del(&dkw);
                    572:        }
                    573: }
                    574:
                    575: /*
                    576:  * dkwedge_list:       [exported function]
                    577:  *
                    578:  *     List all of the wedges on a particular disk.
                    579:  *     If p == NULL, the buffer is in kernel space.  Otherwise, it is
                    580:  *     in user space of the specified process.
                    581:  */
                    582: int
                    583: dkwedge_list(struct disk *pdk, struct dkwedge_list *dkwl, struct proc *p)
                    584: {
                    585:        struct uio uio;
                    586:        struct iovec iov;
                    587:        struct dkwedge_softc *sc;
                    588:        struct dkwedge_info dkw;
                    589:        int error = 0;
                    590:
                    591:        iov.iov_base = dkwl->dkwl_buf;
                    592:        iov.iov_len = dkwl->dkwl_bufsize;
                    593:
                    594:        uio.uio_iov = &iov;
                    595:        uio.uio_iovcnt = 1;
                    596:        uio.uio_offset = 0;
                    597:        uio.uio_resid = dkwl->dkwl_bufsize;
                    598:        uio.uio_segflg = p != NULL ? UIO_USERSPACE : UIO_SYSSPACE;
                    599:        uio.uio_rw = UIO_READ;
                    600:        uio.uio_procp = p;
                    601:
                    602:        dkwl->dkwl_ncopied = 0;
                    603:
                    604:        (void) lockmgr(&pdk->dk_openlock, LK_EXCLUSIVE, NULL);
                    605:        LIST_FOREACH(sc, &pdk->dk_wedges, sc_plink) {
                    606:                if (uio.uio_resid < sizeof(dkw))
                    607:                        break;
                    608:
                    609:                if (sc->sc_state != DKW_STATE_RUNNING)
                    610:                        continue;
                    611:
1.2       thorpej   612:                strcpy(dkw.dkw_devname, sc->sc_dev->dv_xname);
1.1       thorpej   613:                memcpy(dkw.dkw_wname, sc->sc_wname, sizeof(dkw.dkw_wname));
                    614:                dkw.dkw_wname[sizeof(dkw.dkw_wname) - 1] = '\0';
                    615:                strcpy(dkw.dkw_parent, sc->sc_parent->dk_name);
                    616:                dkw.dkw_offset = sc->sc_offset;
                    617:                dkw.dkw_size = sc->sc_size;
                    618:                strcpy(dkw.dkw_ptype, sc->sc_ptype);
                    619:
                    620:                error = uiomove(&dkw, sizeof(dkw), &uio);
                    621:                if (error)
                    622:                        break;
                    623:                dkwl->dkwl_ncopied++;
                    624:        }
                    625:        dkwl->dkwl_nwedges = pdk->dk_nwedges;
                    626:        (void) lockmgr(&pdk->dk_openlock, LK_RELEASE, NULL);
                    627:
                    628:        return (error);
                    629: }
                    630:
                    631: /*
1.3     ! thorpej   632:  * dkwedge_set_bootwedge
        !           633:  *
        !           634:  *     Set the booted_wedge global based on the specified parent name
        !           635:  *     and offset/length.
        !           636:  */
        !           637: void
        !           638: dkwedge_set_bootwedge(struct device *parent, daddr_t startblk, uint64_t nblks)
        !           639: {
        !           640:        struct dkwedge_softc *sc;
        !           641:        int i;
        !           642:
        !           643:        (void) lockmgr(&dkwedges_lock, LK_EXCLUSIVE, NULL);
        !           644:        for (i = 0; i < ndkwedges; i++) {
        !           645:                if ((sc = dkwedges[i]) == NULL)
        !           646:                        continue;
        !           647:                if (strcmp(sc->sc_parent->dk_name, parent->dv_xname) == 0 &&
        !           648:                    sc->sc_offset == startblk &&
        !           649:                    sc->sc_size == nblks) {
        !           650:                        if (booted_wedge) {
        !           651:                                printf("WARNING: double match for boot wedge "
        !           652:                                    "(%s, %s)\n",
        !           653:                                    booted_wedge->dv_xname,
        !           654:                                    sc->sc_dev->dv_xname);
        !           655:                                continue;
        !           656:                        }
        !           657:                        booted_device = parent;
        !           658:                        booted_wedge = sc->sc_dev;
        !           659:                        booted_partition = 0;
        !           660:                }
        !           661:        }
        !           662:        /*
        !           663:         * XXX What if we don't find one?  Should we create a special
        !           664:         * XXX root wedge?
        !           665:         */
        !           666:        (void) lockmgr(&dkwedges_lock, LK_RELEASE, NULL);
        !           667: }
        !           668:
        !           669: /*
1.1       thorpej   670:  * We need a dummy objet to stuff into the dkwedge discovery method link
                    671:  * set to ensure that there is always at least one object in the set.
                    672:  */
                    673: static struct dkwedge_discovery_method dummy_discovery_method;
                    674: __link_set_add_bss(dkwedge_methods, dummy_discovery_method);
                    675:
                    676: /*
                    677:  * dkwedge_discover_init:
                    678:  *
                    679:  *     Initialize the disk wedge discovery method list.
                    680:  */
                    681: static void
                    682: dkwedge_discover_init(void)
                    683: {
                    684:        __link_set_decl(dkwedge_methods, struct dkwedge_discovery_method);
                    685:        struct dkwedge_discovery_method * const *ddmp;
                    686:        struct dkwedge_discovery_method *lddm, *ddm;
                    687:
                    688:        (void) lockmgr(&dkwedge_discovery_methods_lock, LK_EXCLUSIVE, NULL);
                    689:
                    690:        if (dkwedge_discovery_methods_initialized) {
                    691:                (void) lockmgr(&dkwedge_discovery_methods_lock, LK_RELEASE,
                    692:                               NULL);
                    693:                return;
                    694:        }
                    695:
                    696:        LIST_INIT(&dkwedge_discovery_methods);
                    697:
                    698:        __link_set_foreach(ddmp, dkwedge_methods) {
                    699:                ddm = *ddmp;
                    700:                if (ddm == &dummy_discovery_method)
                    701:                        continue;
                    702:                if (LIST_EMPTY(&dkwedge_discovery_methods)) {
                    703:                        LIST_INSERT_HEAD(&dkwedge_discovery_methods,
                    704:                                         ddm, ddm_list);
                    705:                        continue;
                    706:                }
                    707:                LIST_FOREACH(lddm, &dkwedge_discovery_methods, ddm_list) {
                    708:                        if (ddm->ddm_priority == lddm->ddm_priority) {
                    709:                                aprint_error("dk-method-%s: method \"%s\" "
                    710:                                    "already exists at priority %d\n",
                    711:                                    ddm->ddm_name, lddm->ddm_name,
                    712:                                    lddm->ddm_priority);
                    713:                                /* Not inserted. */
                    714:                                break;
                    715:                        }
                    716:                        if (ddm->ddm_priority < lddm->ddm_priority) {
                    717:                                /* Higher priority; insert before. */
                    718:                                LIST_INSERT_BEFORE(lddm, ddm, ddm_list);
                    719:                                break;
                    720:                        }
                    721:                        if (LIST_NEXT(lddm, ddm_list) == NULL) {
                    722:                                /* Last one; insert after. */
                    723:                                KASSERT(lddm->ddm_priority < ddm->ddm_priority);
                    724:                                LIST_INSERT_AFTER(lddm, ddm, ddm_list);
                    725:                                break;
                    726:                        }
                    727:                }
                    728:        }
                    729:
                    730:        dkwedge_discovery_methods_initialized = 1;
                    731:
                    732:        (void) lockmgr(&dkwedge_discovery_methods_lock, LK_RELEASE, NULL);
                    733: }
                    734:
                    735: #ifdef DKWEDGE_AUTODISCOVER
                    736: int    dkwedge_autodiscover = 1;
                    737: #else
                    738: int    dkwedge_autodiscover = 0;
                    739: #endif
                    740:
                    741: /*
                    742:  * dkwedge_discover:   [exported function]
                    743:  *
                    744:  *     Discover the wedges on a newly attached disk.
                    745:  */
                    746: void
                    747: dkwedge_discover(struct disk *pdk)
                    748: {
                    749:        struct dkwedge_discovery_method *ddm;
                    750:        struct vnode *vp;
                    751:        int error;
                    752:        dev_t pdev;
                    753:
                    754:        /*
                    755:         * Require people playing with wedges to enable this explicitly.
                    756:         */
                    757:        if (dkwedge_autodiscover == 0)
                    758:                return;
                    759:
                    760:        if (dkwedge_discovery_methods_initialized == 0)
                    761:                dkwedge_discover_init();
                    762:
                    763:        (void) lockmgr(&dkwedge_discovery_methods_lock, LK_SHARED, NULL);
                    764:
                    765:        error = dkwedge_compute_pdev(pdk->dk_name, &pdev);
                    766:        if (error) {
                    767:                aprint_error("%s: unable to compute pdev, error = %d\n",
                    768:                    pdk->dk_name, error);
                    769:                goto out;
                    770:        }
                    771:
                    772:        error = bdevvp(pdev, &vp);
                    773:        if (error) {
                    774:                aprint_error("%s: unable to find vnode for pdev, error = %d\n",
                    775:                    pdk->dk_name, error);
                    776:                goto out;
                    777:        }
                    778:
                    779:        error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    780:        if (error) {
                    781:                aprint_error("%s: unable to lock vnode for pdev, error = %d\n",
                    782:                    pdk->dk_name, error);
                    783:                vrele(vp);
                    784:                goto out;
                    785:        }
                    786:
                    787:        error = VOP_OPEN(vp, FREAD | FWRITE, NOCRED, 0);
                    788:        if (error) {
                    789:                aprint_error("%s: unable to open device, error = %d\n",
                    790:                    pdk->dk_name, error);
                    791:                vput(vp);
                    792:                goto out;
                    793:        }
                    794:        /* VOP_OPEN() doesn't do this for us. */
                    795:        vp->v_writecount++;
                    796:        VOP_UNLOCK(vp, 0);
                    797:
                    798:        /*
                    799:         * For each supported partition map type, look to see if
                    800:         * this map type exists.  If so, parse it and add the
                    801:         * corresponding wedges.
                    802:         */
                    803:        LIST_FOREACH(ddm, &dkwedge_discovery_methods, ddm_list) {
                    804:                error = (*ddm->ddm_discover)(pdk, vp);
                    805:                if (error == 0) {
                    806:                        /* Successfully created wedges; we're done. */
                    807:                        break;
                    808:                }
                    809:        }
                    810:
                    811:        error = vn_close(vp, FREAD | FWRITE, NOCRED, curproc);
                    812:        if (error) {
                    813:                aprint_error("%s: unable to close device, error = %d\n",
                    814:                    pdk->dk_name, error);
                    815:                /* We'll just assume the vnode has been cleaned up. */
                    816:        }
                    817:  out:
                    818:        (void) lockmgr(&dkwedge_discovery_methods_lock, LK_RELEASE, NULL);
                    819: }
                    820:
                    821: /*
                    822:  * dkwedge_read:
                    823:  *
                    824:  *     Read the some data from the specified disk, used for
                    825:  *     partition discovery.
                    826:  */
                    827: int
                    828: dkwedge_read(struct disk *pdk, struct vnode *vp, daddr_t blkno, void *buf,
                    829:     size_t len)
                    830: {
                    831:        struct buf b;
                    832:
                    833:        BUF_INIT(&b);
                    834:
                    835:        b.b_vp = vp;
                    836:        b.b_dev = vp->v_rdev;
                    837:        b.b_blkno = blkno;
                    838:        b.b_bcount = b.b_resid = len;
                    839:        b.b_flags = B_READ;
                    840:        b.b_proc = curproc;
                    841:        b.b_data = buf;
                    842:
                    843:        VOP_STRATEGY(vp, &b);
                    844:        return (biowait(&b));
                    845: }
                    846:
                    847: /*
                    848:  * dkwedge_lookup:
                    849:  *
                    850:  *     Look up a dkwedge_softc based on the provided dev_t.
                    851:  */
                    852: static struct dkwedge_softc *
                    853: dkwedge_lookup(dev_t dev)
                    854: {
1.3     ! thorpej   855:        int unit = minor(dev);
1.1       thorpej   856:
                    857:        if (unit >= ndkwedges)
                    858:                return (NULL);
                    859:
                    860:        KASSERT(dkwedges != NULL);
                    861:
                    862:        return (dkwedges[unit]);
                    863: }
                    864:
                    865: /*
                    866:  * dkopen:             [devsw entry point]
                    867:  *
                    868:  *     Open a wedge.
                    869:  */
                    870: static int
                    871: dkopen(dev_t dev, int flags, int fmt, struct proc *p)
                    872: {
                    873:        struct dkwedge_softc *sc = dkwedge_lookup(dev);
                    874:        struct vnode *vp;
                    875:        int error;
                    876:
                    877:        if (sc == NULL)
                    878:                return (ENODEV);
                    879:
                    880:        if (sc->sc_state != DKW_STATE_RUNNING)
                    881:                return (ENXIO);
                    882:
                    883:        /*
                    884:         * We go through a complicated little dance to only open the parent
                    885:         * vnode once per wedge, no matter how many times the wedge is
                    886:         * opened.  The reason?  We see one dkopen() per open call, but
                    887:         * only dkclose() on the last close.
                    888:         */
1.3     ! thorpej   889:        (void) lockmgr(&sc->sc_dk.dk_openlock, LK_EXCLUSIVE, NULL);
1.1       thorpej   890:        (void) lockmgr(&sc->sc_parent->dk_rawlock, LK_EXCLUSIVE, NULL);
1.3     ! thorpej   891:        if (sc->sc_dk.dk_openmask == 0) {
1.1       thorpej   892:                if (sc->sc_parent->dk_rawopens++ == 0) {
                    893:                        KASSERT(sc->sc_parent->dk_rawvp == NULL);
                    894:                        error = bdevvp(sc->sc_pdev, &vp);
                    895:                        if (error)
                    896:                                goto popen_fail;
                    897:                        error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    898:                        if (error) {
                    899:                                vrele(vp);
                    900:                                goto popen_fail;
                    901:                        }
                    902:                        error = VOP_OPEN(vp, FREAD | FWRITE, NOCRED, 0);
                    903:                        if (error) {
                    904:                                vput(vp);
                    905:                                goto popen_fail;
                    906:                        }
                    907:                        /* VOP_OPEN() doesn't do this for us. */
                    908:                        vp->v_writecount++;
                    909:                        VOP_UNLOCK(vp, 0);
                    910:                        sc->sc_parent->dk_rawvp = vp;
                    911:                }
1.3     ! thorpej   912:                if (fmt == S_IFCHR)
        !           913:                        sc->sc_dk.dk_copenmask |= 1;
        !           914:                else
        !           915:                        sc->sc_dk.dk_bopenmask |= 1;
        !           916:                sc->sc_dk.dk_openmask =
        !           917:                    sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
1.1       thorpej   918:        }
                    919:        (void) lockmgr(&sc->sc_parent->dk_rawlock, LK_RELEASE, NULL);
1.3     ! thorpej   920:        (void) lockmgr(&sc->sc_dk.dk_openlock, LK_RELEASE, NULL);
1.1       thorpej   921:
                    922:        return (0);
                    923:
                    924:  popen_fail:
                    925:        (void) lockmgr(&sc->sc_parent->dk_rawlock, LK_RELEASE, NULL);
                    926:        return (error);
                    927: }
                    928:
                    929: /*
                    930:  * dkclose:            [devsw entry point]
                    931:  *
                    932:  *     Close a wedge.
                    933:  */
                    934: static int
                    935: dkclose(dev_t dev, int flags, int fmt, struct proc *p)
                    936: {
                    937:        struct dkwedge_softc *sc = dkwedge_lookup(dev);
                    938:        int error = 0;
                    939:
1.3     ! thorpej   940:        KASSERT(sc->sc_dk.dk_openmask != 0);
1.1       thorpej   941:
1.3     ! thorpej   942:        (void) lockmgr(&sc->sc_dk.dk_openlock, LK_EXCLUSIVE, NULL);
1.1       thorpej   943:        (void) lockmgr(&sc->sc_parent->dk_rawlock, LK_EXCLUSIVE, NULL);
                    944:
1.3     ! thorpej   945:        if (fmt == S_IFCHR)
        !           946:                sc->sc_dk.dk_copenmask &= ~1;
        !           947:        else
        !           948:                sc->sc_dk.dk_bopenmask &= ~1;
        !           949:        sc->sc_dk.dk_openmask =
        !           950:            sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
        !           951:
        !           952:        if (sc->sc_dk.dk_openmask == 0) {
        !           953:                if (sc->sc_parent->dk_rawopens-- == 1) {
        !           954:                        KASSERT(sc->sc_parent->dk_rawvp != NULL);
        !           955:                        error = vn_close(sc->sc_parent->dk_rawvp,
        !           956:                                         FREAD | FWRITE, NOCRED, p);
        !           957:                        sc->sc_parent->dk_rawvp = NULL;
        !           958:                }
1.1       thorpej   959:        }
                    960:
                    961:        (void) lockmgr(&sc->sc_parent->dk_rawlock, LK_RELEASE, NULL);
1.3     ! thorpej   962:        (void) lockmgr(&sc->sc_dk.dk_openlock, LK_RELEASE, NULL);
1.1       thorpej   963:
                    964:        return (error);
                    965: }
                    966:
                    967: /*
                    968:  * dkstragegy:         [devsw entry point]
                    969:  *
                    970:  *     Perform I/O based on the wedge I/O strategy.
                    971:  */
                    972: static void
                    973: dkstrategy(struct buf *bp)
                    974: {
                    975:        struct dkwedge_softc *sc = dkwedge_lookup(bp->b_dev);
                    976:        int s;
                    977:
                    978:        if (sc->sc_state != DKW_STATE_RUNNING) {
                    979:                bp->b_error = ENXIO;
                    980:                bp->b_flags |= B_ERROR;
                    981:                goto done;
                    982:        }
                    983:
                    984:        /* If it's an empty transfer, wake up the top half now. */
                    985:        if (bp->b_bcount == 0)
                    986:                goto done;
                    987:
                    988:        /* Make sure it's in-range. */
                    989:        if (bounds_check_with_mediasize(bp, DEV_BSIZE, sc->sc_size) <= 0)
                    990:                goto done;
                    991:
                    992:        /* Translate it to the parent's raw LBA. */
                    993:        bp->b_rawblkno = bp->b_blkno + sc->sc_offset;
                    994:
                    995:        /* Place it in the queue and start I/O on the unit. */
                    996:        s = splbio();
                    997:        sc->sc_iopend++;
                    998:        BUFQ_PUT(&sc->sc_bufq, bp);
                    999:        dkstart(sc);
                   1000:        splx(s);
                   1001:        return;
                   1002:
                   1003:  done:
                   1004:        bp->b_resid = bp->b_bcount;
                   1005:        biodone(bp);
                   1006: }
                   1007:
                   1008: /*
                   1009:  * dkstart:
                   1010:  *
                   1011:  *     Start I/O that has been enqueued on the wedge.
                   1012:  *     NOTE: Must be called at splbio()!
                   1013:  */
                   1014: static void
                   1015: dkstart(struct dkwedge_softc *sc)
                   1016: {
                   1017:        struct buf *bp, *nbp;
                   1018:
                   1019:        /* Do as much work as has been enqueued. */
                   1020:        while ((bp = BUFQ_PEEK(&sc->sc_bufq)) != NULL) {
                   1021:                if (sc->sc_state != DKW_STATE_RUNNING) {
                   1022:                        (void) BUFQ_GET(&sc->sc_bufq);
                   1023:                        if (sc->sc_iopend-- == 1 &&
                   1024:                            (sc->sc_flags & DK_F_WAIT_DRAIN) != 0) {
                   1025:                                sc->sc_flags &= ~DK_F_WAIT_DRAIN;
                   1026:                                wakeup(&sc->sc_iopend);
                   1027:                        }
                   1028:                        bp->b_error = ENXIO;
                   1029:                        bp->b_flags |= B_ERROR;
                   1030:                        bp->b_resid = bp->b_bcount;
                   1031:                        biodone(bp);
                   1032:                }
                   1033:
                   1034:                /* Instrumentation. */
                   1035:                disk_busy(&sc->sc_dk);
                   1036:
                   1037:                nbp = pool_get(&bufpool, PR_NOWAIT);
                   1038:                if (nbp == NULL) {
                   1039:                        /*
                   1040:                         * No resources to run this request; leave the
                   1041:                         * buffer queued up, and schedule a timer to
                   1042:                         * restart the queue in 1/2 a second.
                   1043:                         */
                   1044:                        disk_unbusy(&sc->sc_dk, 0, bp->b_flags & B_READ);
                   1045:                        callout_schedule(&sc->sc_restart_ch, hz / 2);
                   1046:                        return;
                   1047:                }
                   1048:
                   1049:                (void) BUFQ_GET(&sc->sc_bufq);
                   1050:
                   1051:                BUF_INIT(nbp);
                   1052:                nbp->b_data = bp->b_data;
                   1053:                nbp->b_flags = bp->b_flags | B_CALL;
                   1054:                nbp->b_iodone = dkiodone;
                   1055:                nbp->b_proc = bp->b_proc;
                   1056:                nbp->b_blkno = bp->b_rawblkno;
                   1057:                nbp->b_dev = sc->sc_parent->dk_rawvp->v_rdev;
                   1058:                nbp->b_vp = sc->sc_parent->dk_rawvp;
                   1059:                nbp->b_bcount = bp->b_bcount;
                   1060:                nbp->b_private = bp;
                   1061:                BIO_COPYPRIO(nbp, bp);
                   1062:
                   1063:                if ((nbp->b_flags & B_READ) == 0)
                   1064:                        V_INCR_NUMOUTPUT(nbp->b_vp);
                   1065:                VOP_STRATEGY(nbp->b_vp, nbp);
                   1066:        }
                   1067: }
                   1068:
                   1069: /*
                   1070:  * dkiodone:
                   1071:  *
                   1072:  *     I/O to a wedge has completed; alert the top half.
                   1073:  *     NOTE: Must be called at splbio()!
                   1074:  */
                   1075: static void
                   1076: dkiodone(struct buf *bp)
                   1077: {
                   1078:        struct buf *obp = bp->b_private;
                   1079:        struct dkwedge_softc *sc = dkwedge_lookup(obp->b_dev);
                   1080:
                   1081:        if (bp->b_flags & B_ERROR) {
                   1082:                obp->b_flags |= B_ERROR;
                   1083:                obp->b_error = bp->b_error;
                   1084:        }
                   1085:        obp->b_resid = bp->b_resid;
                   1086:        pool_put(&bufpool, bp);
                   1087:
                   1088:        if (sc->sc_iopend-- == 1 && (sc->sc_flags & DK_F_WAIT_DRAIN) != 0) {
                   1089:                sc->sc_flags &= ~DK_F_WAIT_DRAIN;
                   1090:                wakeup(&sc->sc_iopend);
                   1091:        }
                   1092:
                   1093:        disk_unbusy(&sc->sc_dk, obp->b_bcount - obp->b_resid,
                   1094:            obp->b_flags & B_READ);
                   1095:
                   1096:        biodone(obp);
                   1097:
                   1098:        /* Kick the queue in case there is more work we can do. */
                   1099:        dkstart(sc);
                   1100: }
                   1101:
                   1102: /*
                   1103:  * dkrestart:
                   1104:  *
                   1105:  *     Restart the work queue after it was stalled due to
                   1106:  *     a resource shortage.  Invoked via a callout.
                   1107:  */
                   1108: static void
                   1109: dkrestart(void *v)
                   1110: {
                   1111:        struct dkwedge_softc *sc = v;
                   1112:        int s;
                   1113:
                   1114:        s = splbio();
                   1115:        dkstart(sc);
                   1116:        splx(s);
                   1117: }
                   1118:
                   1119: /*
                   1120:  * dkread:             [devsw entry point]
                   1121:  *
                   1122:  *     Read from a wedge.
                   1123:  */
                   1124: static int
                   1125: dkread(dev_t dev, struct uio *uio, int flags)
                   1126: {
                   1127:        struct dkwedge_softc *sc = dkwedge_lookup(dev);
                   1128:
                   1129:        if (sc->sc_state != DKW_STATE_RUNNING)
                   1130:                return (ENXIO);
                   1131:
                   1132:        return (physio(dkstrategy, NULL, dev, B_READ,
                   1133:                       sc->sc_parent->dk_driver->d_minphys, uio));
                   1134: }
                   1135:
                   1136: /*
                   1137:  * dkwrite:            [devsw entry point]
                   1138:  *
                   1139:  *     Write to a wedge.
                   1140:  */
                   1141: static int
                   1142: dkwrite(dev_t dev, struct uio *uio, int flags)
                   1143: {
                   1144:        struct dkwedge_softc *sc = dkwedge_lookup(dev);
                   1145:
                   1146:        if (sc->sc_state != DKW_STATE_RUNNING)
                   1147:                return (ENXIO);
                   1148:
                   1149:        return (physio(dkstrategy, NULL, dev, B_WRITE,
                   1150:                       sc->sc_parent->dk_driver->d_minphys, uio));
                   1151: }
                   1152:
                   1153: /*
                   1154:  * dkioctl:            [devsw entry point]
                   1155:  *
                   1156:  *     Perform an ioctl request on a wedge.
                   1157:  */
                   1158: static int
                   1159: dkioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                   1160: {
                   1161:        struct dkwedge_softc *sc = dkwedge_lookup(dev);
                   1162:        int error = 0;
                   1163:
                   1164:        if (sc->sc_state != DKW_STATE_RUNNING)
                   1165:                return (ENXIO);
                   1166:
                   1167:        switch (cmd) {
                   1168:        case DIOCGWEDGEINFO:
                   1169:            {
                   1170:                struct dkwedge_info *dkw = (void *) data;
                   1171:
1.2       thorpej  1172:                strcpy(dkw->dkw_devname, sc->sc_dev->dv_xname);
1.1       thorpej  1173:                memcpy(dkw->dkw_wname, sc->sc_wname, sizeof(dkw->dkw_wname));
                   1174:                dkw->dkw_wname[sizeof(dkw->dkw_wname) - 1] = '\0';
                   1175:                strcpy(dkw->dkw_parent, sc->sc_parent->dk_name);
                   1176:                dkw->dkw_offset = sc->sc_offset;
                   1177:                dkw->dkw_size = sc->sc_size;
                   1178:                strcpy(dkw->dkw_ptype, sc->sc_ptype);
                   1179:
                   1180:                break;
                   1181:            }
                   1182:
                   1183:        default:
                   1184:                error = ENOTTY;
                   1185:        }
                   1186:
                   1187:        return (error);
                   1188: }
                   1189:
                   1190: /*
                   1191:  * dksize:             [devsw entry point]
                   1192:  *
                   1193:  *     Query the size of a wedge for the purpose of performing a dump
                   1194:  *     or for swapping to.
                   1195:  */
                   1196: static int
                   1197: dksize(dev_t dev)
                   1198: {
                   1199:
                   1200:        /* XXX */
                   1201:        return (-1);
                   1202: }
                   1203:
                   1204: /*
                   1205:  * dkdump:             [devsw entry point]
                   1206:  *
                   1207:  *     Perform a crash dump to a wedge.
                   1208:  */
                   1209: static int
                   1210: dkdump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
                   1211: {
                   1212:
                   1213:        /* XXX */
                   1214:        return (ENXIO);
                   1215: }

CVSweb <webmaster@jp.NetBSD.org>