**Contents**
[[!toc levels=2]]
# Disk driver template when using dksubr library
## Declaration
<pre><code>
const struct bdevsw xxx_bdevsww= {
.d_open = xxxopen,
.d_close = xxxclose,
.d_strategy = xxxstrategy,
.d_ioctl = xxxioctl,
.d_dump = xxxdump,
.d_psize = xxxsize,
.d_discard = xxxdiscard,
.d_flag = D_DISK
};
const struct cdevsw xxx_cdevsw = {
.d_open = xxxopen,
.d_close = xxxclose,
.d_read = xxxread,
.d_write = xxxwrite,
.d_ioctl = xxxioctl,
.d_stop = nostop,
.d_tty = notty,
.d_poll = nopoll,
.d_mmap = nommap,
.d_kqfilter = nokqfilter,
.d_discard = xxxdiscard,
.d_flag = D_DISK
};
static const struct dkdriver xxxdkdriver = {
.d_open = xxxopen,
.d_close = xxxclose,
.d_strategy = xxxstrategy,
.d_iosize = xxx_iosize,
.d_minphys = xxxminphys,
.d_diskstart = xxx_diskstart,
.d_dumpblocks = xxx_dumpblocks,
.d_lastclose = xxx_lastclose,
.d_discard = xxx_discard
};
extern struct cfdriver xxx_cd;
static dev_type_open(xxxopen);
static dev_type_close(xxxclose);
static dev_type_read(xxxread);
static dev_type_write(xxxwrite);
static dev_type_ioctl(xxxioctl);
static dev_type_strategy(xxxstrategy);
static dev_type_dump(xxxdump);
static dev_type_size(xxxsize);
static dev_type_discard(xxxdiscard);
static void xxxminphys(struct buf *bp);
static int xxxdiskstart(device_t, struct buf *bp);
static void xxx_iosize(device_t, int *);
static int xxx_dumpblocks(device_t, void *, daddr_t, int);
static int xxx_lastclose(device_t);
static int xxx_discard(device_t, off_t, off_t);
#define DEVPROLOG \
struct xxx_softc *sc; \
struct dk_softc *dksc; \
int unit; \
\
unit = DISKUNIT(dev); \
if ((sc = device_lookup_private(&xxx_cd, unit)) == NULL) \
return ENXIO; \
dksc = &sc->sc_dksc
</code></pre>
----
## Attachment and Standard driver interface
<pre><code>
void
xxxattach(struct xxx_softc *sc)
{
device_t self = sc->sc_dv;
struct dk_softc *dksc = &sc->sc_dk;
dk_init(dksc, self, DKTYPE_xxx);
disk_init(&dksc->sc_dkdev, dksc->sc_xname, &xxdkdriver);
dk_attach(dksc);
disk_attach(&dksc->sc_dkdev);
// initialize dksc->sc_dkdev.dk_geom
bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
// possibly deferred with config_interrupts()
dkwedge_discover(&dksc->sc_dkdev);
}
static int
xxxopen(dev_t dev, int flags, int fmt, struct lwp *l)
{
DEVPROLOG;
return dk_open(dksc, dev, flags, fmt, l);
}
static int
xxxclose(dev_t dev, int flags, int fmt, struct lwp *l)
{
DEVPROLOG;
return dk_close(dksc, dev, flags, fmt, l);
}
static int
xxxread(dev_t dev, struct uio *uio, int ioflag)
{
return physio(xxxstrategy, NULL, dev, B_READ, xxxminphys, uio);
}
static int
xxxwrite(dev_t dev, struct uio *uio, int ioflag)
{
return physio(xxxstrategy, NULL, dev, B_WRITE, xxxminphys, uio);
}
static int
xxxioctl(dev_t dev, u_long cmd, void *addr, int32_t flag, struct lwp *l)
{
int error;
DEVPROLOG;
error = dk_ioctl(dksc, dev, cmd, addr, flag, l);
if (error != EPASSTHROUGH)
return error;
error = 0;
switch (cmd) {
// private IOCTLs
default:
error = ENOTTY;
}
return error;
}
static void
xxxstrategy(struct buf *bp)
{
DEVPROLOG;
dk_strategy(dksc, bp);
}
static int
xxxdiscard(dev_t dev, off_t pos, off_t len)
{
DEVPROLOG;
return dk_discard(dksc, dev, pos, len);
}
static int
xxxsize(dev_t dev)
{
DEVPROLOG;
return dk_size(dksc, dev);
}
static int
xxxdump(dev_t dev, daddr_t blkno, void *va, size_t size)
{
DEVPROLOG;
return dk_dump(dksc, dev, blkno, va, size);
}
static void
xxxminphys(struct buf *bp)
{
struct xxx_softc *sc;
int unit;
unit = DISKUNIT(bp->b_dev);
if ((sc = device_lookup_private(&xxx_cd, unit)) == NULL)
return;
xxx_iosize(sc->sc_dv, &bp->b_count);
minphys(bp);
}
</code></pre>
----
## I/O callback
<pre><code>
static void
xxxdone(struct xxx_softc *sc, struct buf *bp)
{
struct dk_softc *dksc = &sc->sc_dksc;
dk_done(dksc, bp);
dk_start(dksc, NULL);
}
----
## DK driver interface
static int
xxx_lastclose(device_t dv)
{
// private cleanup
return 0;
}
static int
xxx_diskstart(device_t dv, struct buf *bp)
{
// issue I/O for bp
// return EAGAIN if controller busy
}
static int
xxx_dumpblocks(device_t dv, void *va, daddr_t blkno, int nblk)
{
// issue polling I/O to dump a page
}
static void
xxx_iosize(device_t dv, int *countp)
{
// limit *countp as necessary
}
static int
xxx_discard(device_t dv, off_t pos, off_t len)
{
// issue request to discard bytes
}
----
## Alternative when using a separate I/O thread
static void
xxxstrategy(struct buf *bp)
{
DEVPROLOG;
if (dk_strategy_defer(dksc, bp))
return;
// wake up I/O thread
}
static int
xxx_diskstart(device_t dv, struct buf *bp)
{
// issue I/O for bp
}
static void
xxxdone(struct xxx_softc *sc, struct buf *bp)
{
struct dk_softc *dksc = &sc->sc_dksc;
dk_done(dksc, bp);
// wake up I/O thread
}
static void
xxx_IOTHREAD(struct dk_softc *dksc)
{
while (!shutting_down) {
if (dk_strategy_pending(dksc)
dk_start(dksc, NULL);
// sleep
}
}
</code></pre>
----
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb