--- wikisrc/users/mlelstv/disk-driver-template.mdwn 2015/12/21 10:25:04 1.4 +++ wikisrc/users/mlelstv/disk-driver-template.mdwn 2016/12/08 11:39:34 1.12 @@ -25,7 +25,7 @@ const struct bdevsw xxx_bdevsww= { .d_dump = xxxdump, .d_psize = xxxsize, .d_discard = xxxdiscard, - .d_flag = D_DISK + .d_flag = D_DISK | D_MPSAFE }; const struct cdevsw xxx_cdevsw = { @@ -40,7 +40,7 @@ const struct cdevsw xxx_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = xxxdiscard, - .d_flag = D_DISK + .d_flag = D_DISK | D_MPSAFE }; static void xxxminphys(struct buf *bp); @@ -54,23 +54,40 @@ 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 + .d_discard = xxx_discard, + .d_dumpblocks = xxx_dumpblocks, /* optional */ + .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; +#ifdef PSEUDODEVICE +static void xxxattach(int); +static device_t xxx_create(int); +static int xxx_destroy(device_t); +#endif + +static int xxx_init(device_t); +static int xxx_finish(device_t); + static int xxxdone(struct buf *); @@ -87,27 +104,63 @@ static int xxxdone(struct buf *); ---- -## Attachment and Standard driver interface +## Pseudo-Device Attachment and Standard driver interface
+#ifdef PSEUDODEVICE
void
-xxxattach(struct xxx_softc *sc)
+xxxattach(int num)
{
- device_t self = sc->sc_dv;
- struct dk_softc *dksc = &sc->sc_dk;
+#ifndef _MODULE
+ int error;
- dk_init(dksc, self, DKTYPE_xxx);
- disk_init(&dksc->sc_dkdev, dksc->sc_xname, &xxdkdriver);
+ error = config_cfattach_attach(xxx_cd.cd_name, &xxx_ca);
+ if (error) {
+ aprint_error("%s: unable to register cfattach %d\n",
+ xxx_cd.cd_name, error);
+ return;
+ }
- dk_attach(dksc);
- disk_attach(&dksc->sc_dkdev);
- // initialize dksc->sc_dkdev.dk_geom
+ // some global initialization
+#endif
+}
- 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()
- dkwedge_discover(&dksc->sc_dkdev);
+ return dv;
+}
+
+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
xxxopen(dev_t dev, int flags, int fmt, struct lwp *l)
@@ -224,6 +277,51 @@ xxxdone(struct xxx_softc *sc, struct buf
----
+## Startup and Shutdown
+
+
+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;
+}
+
+
+----
+
## Autoconf interface
@@ -236,22 +334,101 @@ xxx_match(device_t self, cfdata_t cfdata
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)
{
- struct xxx_softc *sc = device_private(self);
- struct dk_softc *dksc = &sc->sc_dksc;
+#ifndef _MODULE
+ xxx_finish(self);
+#endif
+}
- dkwedge_delall(&dksc->sc_dkdev);
+static int
+xxx_activate(device_t self, enum devact act)
+{
+ // switch (act) {
+ // case DVACT_ACTIVATE:
+ // return 0;
+ // case DVACT_DEACTIVATE:
+ // return 0;
+ // }
- dk_drain(dksc);
- bufq_free(dksc->sc_bufq);
+ return EOPNOTSUPP;
+}
+
- dk_detach(dksc);
- disk_detach(&dksc->sc_dkdev);
- disk_destroy(&dksc->sc_dkdev);
+----
+
+## Kernel module interface
+
+
+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;
}
@@ -261,6 +438,14 @@ xxx_detach(device_t self, int flags)
static int
+xxx_firstopen(device_t dv)
+{
+ // private startup
+
+ return 0;
+}
+
+static int
xxx_lastclose(device_t dv)
{
// private cleanup
@@ -279,6 +464,7 @@ static int
xxx_dumpblocks(device_t dv, void *va, daddr_t blkno, int nblk)
{
// issue polling I/O to dump a page
+ // return error
}
static void
@@ -291,7 +477,16 @@ static int
xxx_discard(device_t dv, off_t pos, off_t len)
{
// 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
}
+
----
@@ -310,12 +505,6 @@ xxxstrategy(struct buf *bp)
// 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)
{
@@ -326,7 +515,7 @@ xxxdone(struct xxx_softc *sc, struct buf
}
static void
-xxx_IOTHREAD(struct dk_softc *dksc)
+xxx_iothread(struct dk_softc *dksc)
{
while (!shutting_down) {
if (dk_strategy_pending(dksc))