--- wikisrc/users/mlelstv/disk-driver-template.mdwn 2015/12/21 10:07:51 1.2 +++ wikisrc/users/mlelstv/disk-driver-template.mdwn 2016/12/08 11:39:34 1.12 @@ -7,6 +7,16 @@ ## Declaration

+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= {
 	.d_open = xxxopen,
 	.d_close = xxxclose,
@@ -15,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 = {
@@ -30,39 +40,55 @@ 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);
+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 = {
 	.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;
 
-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);
+#ifdef PSEUDODEVICE
+static void     xxxattach(int);
+static device_t xxx_create(int);
+static int      xxx_destroy(device_t);
+#endif
 
-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 int      xxx_init(device_t);
+static int      xxx_finish(device_t);
+
+static int      xxxdone(struct buf *);
 
 
 #define DEVPROLOG \
@@ -78,27 +104,63 @@ static int      xxx_discard(device_t, of
 
 ----
 
-## 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)
@@ -215,10 +277,175 @@ xxxdone(struct xxx_softc *sc, struct buf
 
 ----
 
-##  DK driver interface
+## 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 + +

+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;
+}
+
+ +---- + +## 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;
+}
+
+ +---- + +## DK driver interface + +

+static int
+xxx_firstopen(device_t dv)
+{
+	// private startup
+
+	return 0;
+}
+
+static int
 xxx_lastclose(device_t dv)
 {
 	// private cleanup
@@ -237,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
@@ -249,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
 }
+
 
---- @@ -268,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) { @@ -284,10 +515,10 @@ 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) + if (dk_strategy_pending(dksc)) dk_start(dksc, NULL); // sleep }