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

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

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