Annotation of wikisrc/users/mlelstv/disk-driver-template.mdwn, revision 1.12

1.1       mlelstv     1: **Contents**
                      2: 
                      3: [[!toc levels=2]]
                      4: 
                      5: # Disk driver template when using dksubr library
                      6: 
                      7: ## Declaration
                      8: 
                      9: <pre><code>
1.4       mlelstv    10: static dev_type_open(xxxopen);
                     11: static dev_type_close(xxxclose);
                     12: static dev_type_read(xxxread);
                     13: static dev_type_write(xxxwrite);
                     14: static dev_type_ioctl(xxxioctl);
                     15: static dev_type_strategy(xxxstrategy);
                     16: static dev_type_dump(xxxdump);
                     17: static dev_type_size(xxxsize);
                     18: static dev_type_discard(xxxdiscard);
                     19: 
1.1       mlelstv    20: const struct bdevsw xxx_bdevsww= {
                     21:        .d_open = xxxopen,
                     22:        .d_close = xxxclose,
                     23:        .d_strategy = xxxstrategy,
                     24:        .d_ioctl = xxxioctl,
                     25:        .d_dump = xxxdump,
                     26:        .d_psize = xxxsize,
                     27:        .d_discard = xxxdiscard,
1.10      mlelstv    28:        .d_flag = D_DISK | D_MPSAFE
1.1       mlelstv    29: };
                     30: 
                     31: const struct cdevsw xxx_cdevsw = {
                     32:        .d_open = xxxopen,
                     33:        .d_close = xxxclose,
                     34:        .d_read = xxxread,
                     35:        .d_write = xxxwrite,
                     36:        .d_ioctl = xxxioctl,
                     37:        .d_stop = nostop,
                     38:        .d_tty = notty,
                     39:        .d_poll = nopoll,
                     40:        .d_mmap = nommap,
                     41:        .d_kqfilter = nokqfilter,
                     42:        .d_discard = xxxdiscard,
1.10      mlelstv    43:        .d_flag = D_DISK | D_MPSAFE
1.1       mlelstv    44: };
                     45: 
1.4       mlelstv    46: static void     xxxminphys(struct buf *bp);
                     47: static int      xxxdiskstart(device_t, struct buf *bp);
                     48: static void     xxx_iosize(device_t, int *);
                     49: static int      xxx_dumpblocks(device_t, void *, daddr_t, int);
                     50: static int      xxx_lastclose(device_t);
                     51: static int      xxx_discard(device_t, off_t, off_t);
                     52: 
1.1       mlelstv    53: static const struct dkdriver xxxdkdriver = {
                     54:        .d_open = xxxopen,
                     55:        .d_close = xxxclose,
                     56:        .d_strategy = xxxstrategy,
                     57:        .d_minphys  = xxxminphys,
                     58:        .d_diskstart = xxx_diskstart,
1.9       mlelstv    59:        .d_discard = xxx_discard,
1.12    ! mlelstv    60:        .d_dumpblocks = xxx_dumpblocks, /* optional */
        !            61:        .d_iosize = xxx_iosize,         /* optional */
        !            62:        .d_lastclose = xxx_lastclose,   /* optional */
        !            63:        .d_firstopen = xxx_firstopen,   /* optional */
        !            64:        .d_label = xxx_label,           /* optional */
1.1       mlelstv    65: };
                     66: 
1.4       mlelstv    67: static int      xxx_match(device_t, cfdata_t, void *);
                     68: static void     xxx_attach(device_t, device_t, void *);
                     69: static int      xxx_detach(device_t, int);
1.11      mlelstv    70: static int      xxx_activate(device_t, enum devact);
1.4       mlelstv    71: 
1.7       mlelstv    72: struct xxx_softc {
                     73:        struct dk_softc         sc_dksc; /* generic disk interface */
                     74:        // private data
                     75: };
                     76: 
1.4       mlelstv    77: CFATTACH_DECL3_NEW(xxx, sizeof(struct xxx_softc),
                     78:     xxx_match, xxx_attach, xxx_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
                     79:     extern struct cfdriver xxx_cd;  
1.1       mlelstv    80: extern struct   cfdriver xxx_cd;
                     81: 
1.5       mlelstv    82: #ifdef PSEUDODEVICE
1.7       mlelstv    83: static void     xxxattach(int);
                     84: static device_t xxx_create(int);
                     85: static int      xxx_destroy(device_t);
1.5       mlelstv    86: #endif
                     87: 
                     88: static int      xxx_init(device_t);
                     89: static int      xxx_finish(device_t);
                     90: 
1.4       mlelstv    91: static int      xxxdone(struct buf *);
1.1       mlelstv    92: 
                     93: 
                     94: #define DEVPROLOG \
                     95:        struct xxx_softc *sc; \
                     96:        struct dk_softc *dksc; \
                     97:        int unit; \
                     98: \
                     99:        unit = DISKUNIT(dev); \
                    100:        if ((sc = device_lookup_private(&xxx_cd, unit)) == NULL) \
                    101:                return ENXIO; \
                    102:        dksc = &sc->sc_dksc
                    103: </code></pre>
                    104: 
                    105: ----
                    106: 
1.5       mlelstv   107: ## Pseudo-Device Attachment and Standard driver interface
1.1       mlelstv   108: 
                    109: <pre><code>
1.5       mlelstv   110: #ifdef PSEUDODEVICE
1.1       mlelstv   111: void
1.5       mlelstv   112: xxxattach(int num)
1.1       mlelstv   113: {
1.7       mlelstv   114: #ifndef _MODULE
1.5       mlelstv   115:        int error;
1.1       mlelstv   116: 
1.5       mlelstv   117:        error = config_cfattach_attach(xxx_cd.cd_name, &xxx_ca);
                    118:        if (error) {
                    119:                aprint_error("%s: unable to register cfattach %d\n",
                    120:                    xxx_cd.cd_name, error);
                    121:                return;
                    122:        }
1.1       mlelstv   123: 
1.5       mlelstv   124:        // some global initialization
1.7       mlelstv   125: #endif
                    126: }
                    127: 
                    128: static device_t
                    129: xxx_create(int unit)
                    130: {
                    131:        cfdata_t cf;
                    132:        device_t dv;
                    133: 
                    134:        cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
                    135:        cf->cf_name = xxx_cd.cd_name;
                    136:        cf->cf_atname = xxx_cd.cd_name;
                    137:        cf->cf_unit = unit;
                    138:        cf->cf_fstate = FSTATE_STAR;
                    139: 
                    140:        dv = config_attach_pseudo(cf);
                    141:        if (dv == NULL) {
                    142:                aprint_error("%s: failed to attach pseudo device\n",
                    143:                    xxx_cd.cd_name);
                    144:                free(cf, M_DEVBUF);
                    145:        }
                    146: 
                    147:        return dv;
                    148: }
                    149: 
                    150: static int
                    151: xxx_destroy(device_t dv)
                    152: {
                    153:        int error;
                    154:        cfdata_t cf;
                    155: 
                    156:        cf = device_cfdata(dv);
                    157:        error = config_detach(dev, DETACH_QUIET);
                    158:        if (error)
                    159:                return error;
                    160:        free(cf, M_DEVBUF);
                    161:        return 0;
1.1       mlelstv   162: }
1.5       mlelstv   163: #endif
1.1       mlelstv   164: 
                    165: static int
                    166: xxxopen(dev_t dev, int flags, int fmt, struct lwp *l)
                    167: {
                    168:        DEVPROLOG;
                    169: 
                    170:        return dk_open(dksc, dev, flags, fmt, l);
                    171: }
                    172: 
                    173: static int
                    174: xxxclose(dev_t dev, int flags, int fmt, struct lwp *l)
                    175: {
                    176:        DEVPROLOG;
                    177: 
                    178:        return dk_close(dksc, dev, flags, fmt, l);
                    179: }
                    180: 
                    181: static int
                    182: xxxread(dev_t dev, struct uio *uio, int ioflag)
                    183: {
                    184: 
                    185:        return physio(xxxstrategy, NULL, dev, B_READ, xxxminphys, uio);
                    186: }
                    187: 
                    188: static int
                    189: xxxwrite(dev_t dev, struct uio *uio, int ioflag)
                    190: {
                    191: 
                    192:        return physio(xxxstrategy, NULL, dev, B_WRITE, xxxminphys, uio);
                    193: }
                    194: 
                    195: static int
                    196: xxxioctl(dev_t dev, u_long cmd, void *addr, int32_t flag, struct lwp *l)
                    197: {
                    198:        int error;
                    199:        DEVPROLOG;
                    200: 
                    201:        error = dk_ioctl(dksc, dev, cmd, addr, flag, l);
                    202:        if (error != EPASSTHROUGH)
                    203:                return error;
                    204: 
                    205:        error = 0;
                    206: 
                    207:        switch (cmd) {
                    208:        // private IOCTLs
                    209:        default:
                    210:                error = ENOTTY;
                    211:        }
                    212: 
                    213:        return error;
                    214: }
                    215: 
                    216: static void
                    217: xxxstrategy(struct buf *bp)
                    218: {
                    219:        DEVPROLOG;
                    220: 
                    221:        dk_strategy(dksc, bp);
                    222: }
                    223: 
                    224: static int
                    225: xxxdiscard(dev_t dev, off_t pos, off_t len)
                    226: {
                    227:        DEVPROLOG;
                    228: 
                    229:        return dk_discard(dksc, dev, pos, len);
                    230: }
                    231: 
                    232: static int
                    233: xxxsize(dev_t dev)
                    234: {
                    235:        DEVPROLOG;
                    236: 
                    237:        return dk_size(dksc, dev);
                    238: }
                    239: 
                    240: static int
                    241: xxxdump(dev_t dev, daddr_t blkno, void *va, size_t size)
                    242: {
                    243:        DEVPROLOG;
                    244: 
                    245:        return dk_dump(dksc, dev, blkno, va, size);
                    246: }
                    247: 
                    248: static void
                    249: xxxminphys(struct buf *bp)
                    250: {
                    251:        struct xxx_softc *sc;
                    252:        int unit;
                    253: 
                    254:        unit = DISKUNIT(bp->b_dev);
                    255:        if ((sc = device_lookup_private(&xxx_cd, unit)) == NULL)
                    256:                return;
                    257: 
                    258:        xxx_iosize(sc->sc_dv, &bp->b_count);
                    259:        minphys(bp);
                    260: }
                    261: </code></pre>
                    262: 
                    263: ----
                    264: 
                    265: ## I/O callback
                    266: 
                    267: <pre><code>
                    268: static void
                    269: xxxdone(struct xxx_softc *sc, struct buf *bp)
                    270: {
                    271:        struct dk_softc *dksc = &sc->sc_dksc;
                    272: 
                    273:        dk_done(dksc, bp);
                    274:        dk_start(dksc, NULL);
                    275: }
1.2       mlelstv   276: </code></pre>
1.1       mlelstv   277: 
                    278: ----
                    279: 
1.5       mlelstv   280: ## Startup and Shutdown
                    281: 
                    282: <pre><code>
                    283: static int
                    284: xxx_init(device_t self)
                    285: {
                    286:        struct xxx_softc *sc = device_private(self);
                    287:        struct dk_softc *dksc = &sc->sc_dk;
                    288: 
                    289:        dk_init(dksc, self, DKTYPE_xxx);
                    290:        disk_init(&dksc->sc_dkdev, dksc->sc_xname, &xxdkdriver);
                    291: 
                    292:        dk_attach(dksc);
                    293:        disk_attach(&dksc->sc_dkdev);
                    294:        // initialize dksc->sc_dkdev.dk_geom
                    295: 
                    296:        bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
                    297: 
                    298:        // possibly deferred with config_interrupts()
                    299:        dkwedge_discover(&dksc->sc_dkdev);
                    300: 
                    301:        return 0;
                    302: }
                    303: 
                    304: static int
                    305: xxx_finish(device_t self)
                    306: {
                    307:        struct xxx_softc *sc = device_private(self);
                    308:        struct dk_softc *dksc = &sc->sc_dksc;
                    309: 
                    310:        dkwedge_delall(&dksc->sc_dkdev);
                    311: 
                    312:        dk_drain(dksc);
                    313:        bufq_free(dksc->sc_bufq);
                    314: 
                    315:        dk_detach(dksc);
                    316:        disk_detach(&dksc->sc_dkdev);
                    317:        disk_destroy(&dksc->sc_dkdev);
                    318: 
                    319:        return 0;
                    320: }
                    321: </code></pre>
                    322: 
                    323: ----
                    324: 
1.4       mlelstv   325: ## Autoconf interface
                    326: 
                    327: <pre><code>
                    328: static int
                    329: xxx_match(device_t self, cfdata_t cfdata, void *aux)
                    330: {
                    331:        return 1;
                    332: }
                    333: 
                    334: static void
                    335: xxx_attach(device_t parent, device_t self, void *aux)
                    336: {
1.5       mlelstv   337: #ifndef _MODULE
                    338:        xxx_init(self);
                    339: #endif
1.4       mlelstv   340: }
                    341: 
                    342: static void
                    343: xxx_detach(device_t self, int flags)
                    344: {
1.5       mlelstv   345: #ifndef _MODULE
                    346:        xxx_finish(self);
                    347: #endif
                    348: }
1.11      mlelstv   349: 
                    350: static int
                    351: xxx_activate(device_t self, enum devact act)
                    352: {
                    353:        // switch (act) {
                    354:        // case DVACT_ACTIVATE:
                    355:        //      return 0;
                    356:        // case DVACT_DEACTIVATE:
                    357:        //      return 0;
                    358:        // }
                    359: 
                    360:        return EOPNOTSUPP;
                    361: }
1.5       mlelstv   362: </code></pre>
                    363: 
                    364: ----
                    365: 
                    366: ## Kernel module interface
                    367: 
                    368: <pre><code>
                    369: MODULE(MODULE_CLASS_DRIVER, xxx, "dk_subr");
1.4       mlelstv   370: 
1.5       mlelstv   371: static int
                    372: xxx_modcmd(modcmd_t cmd, void *data)
                    373: {
                    374:        int error;
                    375: #ifdef _MODULE
                    376:        int bmajor, cmajor;
                    377: #endif
1.4       mlelstv   378: 
1.5       mlelstv   379:        error = 0;
                    380:        switch (cmd) {
                    381:        case MODULE_CMD_INIT:
                    382: #ifdef _MODULE
                    383:                bmajor = cmajor = -1;
                    384:                error = devsw_attach("xxx", &xxx_bdevsw, &bmajor,
                    385:                    &xxx_cdevsw, &cmajor);
                    386:                if (error) {
                    387:                        aprint_error("%s: devsw_attach failed %d\n",
                    388:                            xxx_cd.cd_name, error);
                    389:                        break;
                    390:                }
                    391:                error = config_cfdriver_attach(&xxx_cd);
                    392:                if (error) {
                    393:                        aprint_error("%s: config_cfdriver_attach failed %d\n",
                    394:                            xxx_cd.cd_name, error);
                    395:                        devsw_detach(&xxx_bdevsw, &xxx_cdevsw);
                    396:                        break;
                    397:                }
                    398:                error = config_cfattach_attach(&xxx_cd);
                    399:                if (error) {
                    400:                        aprint_error("%s: config_cfattach_attach failed %d\n",
                    401:                            xxx_cd.cd_name, error);
                    402:                        config_cfdriver_detach(&xxx_cd);
                    403:                        devsw_detach(&xxx_bdevsw, &xxx_cdevsw);
                    404:                        break;
                    405:                }
                    406:                // some global initialization
                    407: 
1.6       mlelstv   408: #ifdef PSEUDODEVICE
                    409:                xxxattach(0);
1.5       mlelstv   410: #endif
                    411:                break;
                    412:        case MODULE_CMD_FINI:
1.6       mlelstv   413:                // outside of #ifdef _MODULE to allow removal of builtins
1.5       mlelstv   414:                // some global finalization
                    415: #ifdef _MODULE
                    416:                error = config_cfattach_detach(&xxx_cd.cd_name, &xxx_ca);
                    417:                if (error)
                    418:                        break;
                    419:                config_cfdriver_detach(&xxx_cd);
                    420:                devsw_detach(&xxx_bdevsw, &xxx_cdevsw);
                    421: #endif
                    422:                break;
                    423:        case MODULE_CMD_STAT:
                    424:                error = ENOTTY;
                    425:                break;
                    426:        default:
                    427:                error = ENOTTY;
                    428:                break;
                    429:        }
1.4       mlelstv   430: 
1.5       mlelstv   431:        return error;
1.4       mlelstv   432: }
                    433: </code></pre>
                    434: 
                    435: ----
                    436: 
                    437: ## DK driver interface
1.1       mlelstv   438: 
1.2       mlelstv   439: <pre><code>
1.1       mlelstv   440: static int
1.8       mlelstv   441: xxx_firstopen(device_t dv)
                    442: {
                    443:        // private startup
                    444: 
                    445:        return 0;
                    446: }
                    447: 
                    448: static int
1.1       mlelstv   449: xxx_lastclose(device_t dv)
                    450: {
                    451:        // private cleanup
                    452: 
                    453:        return 0;
                    454: }
                    455: 
                    456: static int
                    457: xxx_diskstart(device_t dv, struct buf *bp)
                    458: {
                    459:        // issue I/O for bp
                    460:        // return EAGAIN if controller busy
                    461: }
                    462: 
                    463: static int
                    464: xxx_dumpblocks(device_t dv, void *va, daddr_t blkno, int nblk)
                    465: {
                    466:        // issue polling I/O to dump a page
1.12    ! mlelstv   467:        // return error
1.1       mlelstv   468: }
                    469: 
                    470: static void
                    471: xxx_iosize(device_t dv, int *countp)
                    472: {
                    473:        // limit *countp as necessary
                    474: }
                    475: 
                    476: static int
                    477: xxx_discard(device_t dv, off_t pos, off_t len)
                    478: {
                    479:        // issue request to discard bytes
1.12    ! mlelstv   480:        // return error
1.1       mlelstv   481: }
1.12    ! mlelstv   482: 
        !           483: static void
        !           484: xxx_label(device_t dv, struct disklabel *lp)
        !           485: {
        !           486:        // lp is initialized for generic disk
        !           487:        // augment with driver specific information
        !           488: }
        !           489: 
1.2       mlelstv   490: </code></pre>
1.1       mlelstv   491: 
                    492: ----
                    493: 
                    494: ## Alternative when using a separate I/O thread
                    495: 
1.2       mlelstv   496: <pre><code>
1.1       mlelstv   497: static void
                    498: xxxstrategy(struct buf *bp)
                    499: {
                    500:        DEVPROLOG;
                    501: 
                    502:        if (dk_strategy_defer(dksc, bp))
                    503:                return;
                    504: 
                    505:        // wake up I/O thread
                    506: }
                    507: 
                    508: static void
                    509: xxxdone(struct xxx_softc *sc, struct buf *bp)
                    510: {
                    511:        struct dk_softc *dksc = &sc->sc_dksc;
                    512: 
                    513:        dk_done(dksc, bp);
                    514:        // wake up I/O thread
                    515: }
                    516: 
                    517: static void
1.10      mlelstv   518: xxx_iothread(struct dk_softc *dksc)
1.1       mlelstv   519: {
                    520:        while (!shutting_down) {
1.3       mlelstv   521:                if (dk_strategy_pending(dksc))
1.1       mlelstv   522:                        dk_start(dksc, NULL);
                    523:                // sleep
                    524:        }
                    525: }
                    526: </code></pre>
                    527: 
                    528: ----

CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb