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

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

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