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

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

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