version 1.3, 2015/12/21 10:08:45
|
version 1.12, 2016/12/08 11:39:34
|
Line 7
|
Line 7
|
## Declaration |
## Declaration |
|
|
<pre><code> |
<pre><code> |
|
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); |
|
|
const struct bdevsw xxx_bdevsww= { |
const struct bdevsw xxx_bdevsww= { |
.d_open = xxxopen, |
.d_open = xxxopen, |
.d_close = xxxclose, |
.d_close = xxxclose, |
Line 15 const struct bdevsw xxx_bdevsww= {
|
Line 25 const struct bdevsw xxx_bdevsww= {
|
.d_dump = xxxdump, |
.d_dump = xxxdump, |
.d_psize = xxxsize, |
.d_psize = xxxsize, |
.d_discard = xxxdiscard, |
.d_discard = xxxdiscard, |
.d_flag = D_DISK |
.d_flag = D_DISK | D_MPSAFE |
}; |
}; |
|
|
const struct cdevsw xxx_cdevsw = { |
const struct cdevsw xxx_cdevsw = { |
Line 30 const struct cdevsw xxx_cdevsw = {
|
Line 40 const struct cdevsw xxx_cdevsw = {
|
.d_mmap = nommap, |
.d_mmap = nommap, |
.d_kqfilter = nokqfilter, |
.d_kqfilter = nokqfilter, |
.d_discard = xxxdiscard, |
.d_discard = xxxdiscard, |
.d_flag = D_DISK |
.d_flag = D_DISK | D_MPSAFE |
}; |
}; |
|
|
|
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); |
|
|
static const struct dkdriver xxxdkdriver = { |
static const struct dkdriver xxxdkdriver = { |
.d_open = xxxopen, |
.d_open = xxxopen, |
.d_close = xxxclose, |
.d_close = xxxclose, |
.d_strategy = xxxstrategy, |
.d_strategy = xxxstrategy, |
.d_iosize = xxx_iosize, |
|
.d_minphys = xxxminphys, |
.d_minphys = xxxminphys, |
.d_diskstart = xxx_diskstart, |
.d_diskstart = xxx_diskstart, |
.d_dumpblocks = xxx_dumpblocks, |
.d_discard = xxx_discard, |
.d_lastclose = xxx_lastclose, |
.d_dumpblocks = xxx_dumpblocks, /* optional */ |
.d_discard = xxx_discard |
.d_iosize = xxx_iosize, /* optional */ |
|
.d_lastclose = xxx_lastclose, /* optional */ |
|
.d_firstopen = xxx_firstopen, /* optional */ |
|
.d_label = xxx_label, /* optional */ |
|
}; |
|
|
|
static int xxx_match(device_t, cfdata_t, void *); |
|
static void xxx_attach(device_t, device_t, void *); |
|
static int xxx_detach(device_t, int); |
|
static int xxx_activate(device_t, enum devact); |
|
|
|
struct xxx_softc { |
|
struct dk_softc sc_dksc; /* generic disk interface */ |
|
// private data |
}; |
}; |
|
|
|
CFATTACH_DECL3_NEW(xxx, sizeof(struct xxx_softc), |
|
xxx_match, xxx_attach, xxx_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); |
|
extern struct cfdriver xxx_cd; |
extern struct cfdriver xxx_cd; |
extern struct cfdriver xxx_cd; |
|
|
static dev_type_open(xxxopen); |
#ifdef PSEUDODEVICE |
static dev_type_close(xxxclose); |
static void xxxattach(int); |
static dev_type_read(xxxread); |
static device_t xxx_create(int); |
static dev_type_write(xxxwrite); |
static int xxx_destroy(device_t); |
static dev_type_ioctl(xxxioctl); |
#endif |
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 xxx_init(device_t); |
static int xxxdiskstart(device_t, struct buf *bp); |
static int xxx_finish(device_t); |
static void xxx_iosize(device_t, int *); |
|
static int xxx_dumpblocks(device_t, void *, daddr_t, int); |
static int xxxdone(struct buf *); |
static int xxx_lastclose(device_t); |
|
static int xxx_discard(device_t, off_t, off_t); |
|
|
|
|
|
#define DEVPROLOG \ |
#define DEVPROLOG \ |
Line 78 static int xxx_discard(device_t, of
|
Line 104 static int xxx_discard(device_t, of
|
|
|
---- |
---- |
|
|
## Attachment and Standard driver interface |
## Pseudo-Device Attachment and Standard driver interface |
|
|
<pre><code> |
<pre><code> |
|
#ifdef PSEUDODEVICE |
void |
void |
xxxattach(struct xxx_softc *sc) |
xxxattach(int num) |
{ |
{ |
device_t self = sc->sc_dv; |
#ifndef _MODULE |
struct dk_softc *dksc = &sc->sc_dk; |
int error; |
|
|
dk_init(dksc, self, DKTYPE_xxx); |
error = config_cfattach_attach(xxx_cd.cd_name, &xxx_ca); |
disk_init(&dksc->sc_dkdev, dksc->sc_xname, &xxdkdriver); |
if (error) { |
|
aprint_error("%s: unable to register cfattach %d\n", |
|
xxx_cd.cd_name, error); |
|
return; |
|
} |
|
|
dk_attach(dksc); |
// some global initialization |
disk_attach(&dksc->sc_dkdev); |
#endif |
// initialize dksc->sc_dkdev.dk_geom |
} |
|
|
bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK); |
static device_t |
|
xxx_create(int unit) |
|
{ |
|
cfdata_t cf; |
|
device_t dv; |
|
|
|
cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK); |
|
cf->cf_name = xxx_cd.cd_name; |
|
cf->cf_atname = xxx_cd.cd_name; |
|
cf->cf_unit = unit; |
|
cf->cf_fstate = FSTATE_STAR; |
|
|
|
dv = config_attach_pseudo(cf); |
|
if (dv == NULL) { |
|
aprint_error("%s: failed to attach pseudo device\n", |
|
xxx_cd.cd_name); |
|
free(cf, M_DEVBUF); |
|
} |
|
|
// possibly deferred with config_interrupts() |
return dv; |
dkwedge_discover(&dksc->sc_dkdev); |
} |
|
|
|
static int |
|
xxx_destroy(device_t dv) |
|
{ |
|
int error; |
|
cfdata_t cf; |
|
|
|
cf = device_cfdata(dv); |
|
error = config_detach(dev, DETACH_QUIET); |
|
if (error) |
|
return error; |
|
free(cf, M_DEVBUF); |
|
return 0; |
} |
} |
|
#endif |
|
|
static int |
static int |
xxxopen(dev_t dev, int flags, int fmt, struct lwp *l) |
xxxopen(dev_t dev, int flags, int fmt, struct lwp *l) |
Line 215 xxxdone(struct xxx_softc *sc, struct buf
|
Line 277 xxxdone(struct xxx_softc *sc, struct buf
|
|
|
---- |
---- |
|
|
## DK driver interface |
## Startup and Shutdown |
|
|
<pre><code> |
<pre><code> |
static int |
static int |
|
xxx_init(device_t self) |
|
{ |
|
struct xxx_softc *sc = device_private(self); |
|
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); |
|
|
|
return 0; |
|
} |
|
|
|
static int |
|
xxx_finish(device_t self) |
|
{ |
|
struct xxx_softc *sc = device_private(self); |
|
struct dk_softc *dksc = &sc->sc_dksc; |
|
|
|
dkwedge_delall(&dksc->sc_dkdev); |
|
|
|
dk_drain(dksc); |
|
bufq_free(dksc->sc_bufq); |
|
|
|
dk_detach(dksc); |
|
disk_detach(&dksc->sc_dkdev); |
|
disk_destroy(&dksc->sc_dkdev); |
|
|
|
return 0; |
|
} |
|
</code></pre> |
|
|
|
---- |
|
|
|
## Autoconf interface |
|
|
|
<pre><code> |
|
static int |
|
xxx_match(device_t self, cfdata_t cfdata, void *aux) |
|
{ |
|
return 1; |
|
} |
|
|
|
static void |
|
xxx_attach(device_t parent, device_t self, void *aux) |
|
{ |
|
#ifndef _MODULE |
|
xxx_init(self); |
|
#endif |
|
} |
|
|
|
static void |
|
xxx_detach(device_t self, int flags) |
|
{ |
|
#ifndef _MODULE |
|
xxx_finish(self); |
|
#endif |
|
} |
|
|
|
static int |
|
xxx_activate(device_t self, enum devact act) |
|
{ |
|
// switch (act) { |
|
// case DVACT_ACTIVATE: |
|
// return 0; |
|
// case DVACT_DEACTIVATE: |
|
// return 0; |
|
// } |
|
|
|
return EOPNOTSUPP; |
|
} |
|
</code></pre> |
|
|
|
---- |
|
|
|
## Kernel module interface |
|
|
|
<pre><code> |
|
MODULE(MODULE_CLASS_DRIVER, xxx, "dk_subr"); |
|
|
|
static int |
|
xxx_modcmd(modcmd_t cmd, void *data) |
|
{ |
|
int error; |
|
#ifdef _MODULE |
|
int bmajor, cmajor; |
|
#endif |
|
|
|
error = 0; |
|
switch (cmd) { |
|
case MODULE_CMD_INIT: |
|
#ifdef _MODULE |
|
bmajor = cmajor = -1; |
|
error = devsw_attach("xxx", &xxx_bdevsw, &bmajor, |
|
&xxx_cdevsw, &cmajor); |
|
if (error) { |
|
aprint_error("%s: devsw_attach failed %d\n", |
|
xxx_cd.cd_name, error); |
|
break; |
|
} |
|
error = config_cfdriver_attach(&xxx_cd); |
|
if (error) { |
|
aprint_error("%s: config_cfdriver_attach failed %d\n", |
|
xxx_cd.cd_name, error); |
|
devsw_detach(&xxx_bdevsw, &xxx_cdevsw); |
|
break; |
|
} |
|
error = config_cfattach_attach(&xxx_cd); |
|
if (error) { |
|
aprint_error("%s: config_cfattach_attach failed %d\n", |
|
xxx_cd.cd_name, error); |
|
config_cfdriver_detach(&xxx_cd); |
|
devsw_detach(&xxx_bdevsw, &xxx_cdevsw); |
|
break; |
|
} |
|
// some global initialization |
|
|
|
#ifdef PSEUDODEVICE |
|
xxxattach(0); |
|
#endif |
|
break; |
|
case MODULE_CMD_FINI: |
|
// outside of #ifdef _MODULE to allow removal of builtins |
|
// some global finalization |
|
#ifdef _MODULE |
|
error = config_cfattach_detach(&xxx_cd.cd_name, &xxx_ca); |
|
if (error) |
|
break; |
|
config_cfdriver_detach(&xxx_cd); |
|
devsw_detach(&xxx_bdevsw, &xxx_cdevsw); |
|
#endif |
|
break; |
|
case MODULE_CMD_STAT: |
|
error = ENOTTY; |
|
break; |
|
default: |
|
error = ENOTTY; |
|
break; |
|
} |
|
|
|
return error; |
|
} |
|
</code></pre> |
|
|
|
---- |
|
|
|
## DK driver interface |
|
|
|
<pre><code> |
|
static int |
|
xxx_firstopen(device_t dv) |
|
{ |
|
// private startup |
|
|
|
return 0; |
|
} |
|
|
|
static int |
xxx_lastclose(device_t dv) |
xxx_lastclose(device_t dv) |
{ |
{ |
// private cleanup |
// private cleanup |
Line 237 static int
|
Line 464 static int
|
xxx_dumpblocks(device_t dv, void *va, daddr_t blkno, int nblk) |
xxx_dumpblocks(device_t dv, void *va, daddr_t blkno, int nblk) |
{ |
{ |
// issue polling I/O to dump a page |
// issue polling I/O to dump a page |
|
// return error |
} |
} |
|
|
static void |
static void |
Line 249 static int
|
Line 477 static int
|
xxx_discard(device_t dv, off_t pos, off_t len) |
xxx_discard(device_t dv, off_t pos, off_t len) |
{ |
{ |
// issue request to discard bytes |
// issue request to discard bytes |
|
// return error |
|
} |
|
|
|
static void |
|
xxx_label(device_t dv, struct disklabel *lp) |
|
{ |
|
// lp is initialized for generic disk |
|
// augment with driver specific information |
} |
} |
|
|
</code></pre> |
</code></pre> |
|
|
---- |
---- |
Line 268 xxxstrategy(struct buf *bp)
|
Line 505 xxxstrategy(struct buf *bp)
|
// wake up I/O thread |
// wake up I/O thread |
} |
} |
|
|
static int |
|
xxx_diskstart(device_t dv, struct buf *bp) |
|
{ |
|
// issue I/O for bp |
|
} |
|
|
|
static void |
static void |
xxxdone(struct xxx_softc *sc, struct buf *bp) |
xxxdone(struct xxx_softc *sc, struct buf *bp) |
{ |
{ |
Line 284 xxxdone(struct xxx_softc *sc, struct buf
|
Line 515 xxxdone(struct xxx_softc *sc, struct buf
|
} |
} |
|
|
static void |
static void |
xxx_IOTHREAD(struct dk_softc *dksc) |
xxx_iothread(struct dk_softc *dksc) |
{ |
{ |
while (!shutting_down) { |
while (!shutting_down) { |
if (dk_strategy_pending(dksc)) |
if (dk_strategy_pending(dksc)) |