--- wikisrc/users/mlelstv/disk-driver-template.mdwn 2015/12/21 10:25:04 1.4 +++ wikisrc/users/mlelstv/disk-driver-template.mdwn 2015/12/21 11:44:20 1.5 @@ -71,6 +71,13 @@ CFATTACH_DECL3_NEW(xxx, sizeof(struct xx extern struct cfdriver xxx_cd; extern struct cfdriver xxx_cd; +#ifdef PSEUDODEVICE +static void xxxattach(int num); +#endif + +static int xxx_init(device_t); +static int xxx_finish(device_t); + static int xxxdone(struct buf *); @@ -87,27 +94,25 @@ 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;
-
- 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
+ int error;
- bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
+ 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;
+ }
- // possibly deferred with config_interrupts()
- dkwedge_discover(&dksc->sc_dkdev);
+ // some global initialization
}
+#endif
static int
xxxopen(dev_t dev, int flags, int fmt, struct lwp *l)
@@ -224,6 +229,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 +286,94 @@ 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);
+----
- dk_drain(dksc);
- bufq_free(dksc->sc_bufq);
+## Kernel module interface
- dk_detach(dksc);
- disk_detach(&dksc->sc_dkdev);
- disk_destroy(&dksc->sc_dkdev);
+
+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
+
+ // magic happens to create device instances
+
+ // sometimes by calling config_attach_pseudo
+ // sometimes by faking structures manually
+ // using config_attach_loc might be possible
+ // sometimes by calling xxxattach(0) which
+ // uses one of the methods
+#endif
+ break;
+ case MODULE_CMD_FINI:
+ // magic happens to destroy device instances
+
+ // 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;
}