--- 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;
 }