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

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

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