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

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.4     ! mlelstv    74: static int      xxxdone(struct buf *);
1.1       mlelstv    75: 
                     76: 
                     77: #define DEVPROLOG \
                     78:        struct xxx_softc *sc; \
                     79:        struct dk_softc *dksc; \
                     80:        int unit; \
                     81: \
                     82:        unit = DISKUNIT(dev); \
                     83:        if ((sc = device_lookup_private(&xxx_cd, unit)) == NULL) \
                     84:                return ENXIO; \
                     85:        dksc = &sc->sc_dksc
                     86: </code></pre>
                     87: 
                     88: ----
                     89: 
                     90: ## Attachment and Standard driver interface
                     91: 
                     92: <pre><code>
                     93: void
                     94: xxxattach(struct xxx_softc *sc)
                     95: {
                     96:        device_t self = sc->sc_dv;
                     97:        struct dk_softc *dksc = &sc->sc_dk;
                     98: 
                     99:        dk_init(dksc, self, DKTYPE_xxx);
                    100:        disk_init(&dksc->sc_dkdev, dksc->sc_xname, &xxdkdriver);
                    101: 
                    102:        dk_attach(dksc);
                    103:        disk_attach(&dksc->sc_dkdev);
                    104:        // initialize dksc->sc_dkdev.dk_geom
                    105: 
                    106:        bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
                    107: 
                    108:        // possibly deferred with config_interrupts()
                    109:        dkwedge_discover(&dksc->sc_dkdev);
                    110: }
                    111: 
                    112: static int
                    113: xxxopen(dev_t dev, int flags, int fmt, struct lwp *l)
                    114: {
                    115:        DEVPROLOG;
                    116: 
                    117:        return dk_open(dksc, dev, flags, fmt, l);
                    118: }
                    119: 
                    120: static int
                    121: xxxclose(dev_t dev, int flags, int fmt, struct lwp *l)
                    122: {
                    123:        DEVPROLOG;
                    124: 
                    125:        return dk_close(dksc, dev, flags, fmt, l);
                    126: }
                    127: 
                    128: static int
                    129: xxxread(dev_t dev, struct uio *uio, int ioflag)
                    130: {
                    131: 
                    132:        return physio(xxxstrategy, NULL, dev, B_READ, xxxminphys, uio);
                    133: }
                    134: 
                    135: static int
                    136: xxxwrite(dev_t dev, struct uio *uio, int ioflag)
                    137: {
                    138: 
                    139:        return physio(xxxstrategy, NULL, dev, B_WRITE, xxxminphys, uio);
                    140: }
                    141: 
                    142: static int
                    143: xxxioctl(dev_t dev, u_long cmd, void *addr, int32_t flag, struct lwp *l)
                    144: {
                    145:        int error;
                    146:        DEVPROLOG;
                    147: 
                    148:        error = dk_ioctl(dksc, dev, cmd, addr, flag, l);
                    149:        if (error != EPASSTHROUGH)
                    150:                return error;
                    151: 
                    152:        error = 0;
                    153: 
                    154:        switch (cmd) {
                    155:        // private IOCTLs
                    156:        default:
                    157:                error = ENOTTY;
                    158:        }
                    159: 
                    160:        return error;
                    161: }
                    162: 
                    163: static void
                    164: xxxstrategy(struct buf *bp)
                    165: {
                    166:        DEVPROLOG;
                    167: 
                    168:        dk_strategy(dksc, bp);
                    169: }
                    170: 
                    171: static int
                    172: xxxdiscard(dev_t dev, off_t pos, off_t len)
                    173: {
                    174:        DEVPROLOG;
                    175: 
                    176:        return dk_discard(dksc, dev, pos, len);
                    177: }
                    178: 
                    179: static int
                    180: xxxsize(dev_t dev)
                    181: {
                    182:        DEVPROLOG;
                    183: 
                    184:        return dk_size(dksc, dev);
                    185: }
                    186: 
                    187: static int
                    188: xxxdump(dev_t dev, daddr_t blkno, void *va, size_t size)
                    189: {
                    190:        DEVPROLOG;
                    191: 
                    192:        return dk_dump(dksc, dev, blkno, va, size);
                    193: }
                    194: 
                    195: static void
                    196: xxxminphys(struct buf *bp)
                    197: {
                    198:        struct xxx_softc *sc;
                    199:        int unit;
                    200: 
                    201:        unit = DISKUNIT(bp->b_dev);
                    202:        if ((sc = device_lookup_private(&xxx_cd, unit)) == NULL)
                    203:                return;
                    204: 
                    205:        xxx_iosize(sc->sc_dv, &bp->b_count);
                    206:        minphys(bp);
                    207: }
                    208: </code></pre>
                    209: 
                    210: ----
                    211: 
                    212: ## I/O callback
                    213: 
                    214: <pre><code>
                    215: static void
                    216: xxxdone(struct xxx_softc *sc, struct buf *bp)
                    217: {
                    218:        struct dk_softc *dksc = &sc->sc_dksc;
                    219: 
                    220:        dk_done(dksc, bp);
                    221:        dk_start(dksc, NULL);
                    222: }
1.2       mlelstv   223: </code></pre>
1.1       mlelstv   224: 
                    225: ----
                    226: 
1.4     ! mlelstv   227: ## Autoconf interface
        !           228: 
        !           229: <pre><code>
        !           230: static int
        !           231: xxx_match(device_t self, cfdata_t cfdata, void *aux)
        !           232: {
        !           233:        return 1;
        !           234: }
        !           235: 
        !           236: static void
        !           237: xxx_attach(device_t parent, device_t self, void *aux)
        !           238: {
        !           239: }
        !           240: 
        !           241: static void
        !           242: xxx_detach(device_t self, int flags)
        !           243: {
        !           244:        struct xxx_softc *sc = device_private(self);
        !           245:        struct dk_softc *dksc = &sc->sc_dksc;
        !           246: 
        !           247:        dkwedge_delall(&dksc->sc_dkdev);
        !           248: 
        !           249:        dk_drain(dksc);
        !           250:        bufq_free(dksc->sc_bufq);
        !           251: 
        !           252:        dk_detach(dksc);
        !           253:        disk_detach(&dksc->sc_dkdev);
        !           254:        disk_destroy(&dksc->sc_dkdev);
        !           255: }
        !           256: </code></pre>
        !           257: 
        !           258: ----
        !           259: 
        !           260: ## DK driver interface
1.1       mlelstv   261: 
1.2       mlelstv   262: <pre><code>
1.1       mlelstv   263: static int
                    264: xxx_lastclose(device_t dv)
                    265: {
                    266:        // private cleanup
                    267: 
                    268:        return 0;
                    269: }
                    270: 
                    271: static int
                    272: xxx_diskstart(device_t dv, struct buf *bp)
                    273: {
                    274:        // issue I/O for bp
                    275:        // return EAGAIN if controller busy
                    276: }
                    277: 
                    278: static int
                    279: xxx_dumpblocks(device_t dv, void *va, daddr_t blkno, int nblk)
                    280: {
                    281:        // issue polling I/O to dump a page
                    282: }
                    283: 
                    284: static void
                    285: xxx_iosize(device_t dv, int *countp)
                    286: {
                    287:        // limit *countp as necessary
                    288: }
                    289: 
                    290: static int
                    291: xxx_discard(device_t dv, off_t pos, off_t len)
                    292: {
                    293:        // issue request to discard bytes
                    294: }
1.2       mlelstv   295: </code></pre>
1.1       mlelstv   296: 
                    297: ----
                    298: 
                    299: ## Alternative when using a separate I/O thread
                    300: 
1.2       mlelstv   301: <pre><code>
1.1       mlelstv   302: static void
                    303: xxxstrategy(struct buf *bp)
                    304: {
                    305:        DEVPROLOG;
                    306: 
                    307:        if (dk_strategy_defer(dksc, bp))
                    308:                return;
                    309: 
                    310:        // wake up I/O thread
                    311: }
                    312: 
                    313: static int
                    314: xxx_diskstart(device_t dv, struct buf *bp)
                    315: {
                    316:        // issue I/O for bp
                    317: }
                    318: 
                    319: static void
                    320: xxxdone(struct xxx_softc *sc, struct buf *bp)
                    321: {
                    322:        struct dk_softc *dksc = &sc->sc_dksc;
                    323: 
                    324:        dk_done(dksc, bp);
                    325:        // wake up I/O thread
                    326: }
                    327: 
                    328: static void
                    329: xxx_IOTHREAD(struct dk_softc *dksc)
                    330: {
                    331:        while (!shutting_down) {
1.3       mlelstv   332:                if (dk_strategy_pending(dksc))
1.1       mlelstv   333:                        dk_start(dksc, NULL);
                    334:                // sleep
                    335:        }
                    336: }
                    337: </code></pre>
                    338: 
                    339: ----

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