Create fb and vga character devices if available.

diff -ru --exclude-from freebsd-src-diff-exclude-names /usr/src/sys/dev/fb/fb.c freebsd-11.1/sys/dev/fb/fb.c
--- /usr/src/sys/dev/fb/fb.c	2017-07-21 07:41:47.000000000 +0800
+++ freebsd-11.1/sys/dev/fb/fb.c	2020-08-06 13:40:44.116549883 +0800
@@ -67,6 +67,10 @@
 #ifdef FB_INSTALL_CDEV
 static struct cdevsw	*vidcdevsw_ini;
 static struct cdevsw	**vidcdevsw = &vidcdevsw_ini;
+static struct cdev	*fb_dev_ini;
+static struct cdev	**fb_dev = &fb_dev_ini;
+static struct cdev	*va_dev_ini;
+static struct cdev	**va_dev = &va_dev_ini;
 #endif
 
 #define ARRAY_DELTA	4
@@ -78,6 +82,7 @@
 	video_switch_t **new_vidsw;
 #ifdef FB_INSTALL_CDEV
 	struct cdevsw **new_cdevsw;
+	struct cdev **new_fb_dev, **new_va_dev;
 #endif
 	int newsize;
 	int s;
@@ -93,23 +98,33 @@
 #ifdef FB_INSTALL_CDEV
 	new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF,
 	    M_WAITOK | M_ZERO);
+	new_fb_dev = malloc(sizeof(struct cdev *) * newsize, M_DEVBUF,
+		M_WAITOK | M_ZERO);
+	new_va_dev = malloc(sizeof(struct cdev *) * newsize, M_DEVBUF,
+		M_WAITOK | M_ZERO);
 #endif
 	bcopy(adapter, new_adp, sizeof(*adapter)*adapters);
 	bcopy(vidsw, new_vidsw, sizeof(*vidsw)*adapters);
 #ifdef FB_INSTALL_CDEV
 	bcopy(vidcdevsw, new_cdevsw, sizeof(*vidcdevsw)*adapters);
+	memcpy(new_fb_dev, fb_dev, sizeof(struct cdev *) * adapters);
+	memcpy(new_va_dev, va_dev, sizeof(struct cdev *) * adapters);
 #endif
 	if (adapters > 1) {
 		free(adapter, M_DEVBUF);
 		free(vidsw, M_DEVBUF);
 #ifdef FB_INSTALL_CDEV
 		free(vidcdevsw, M_DEVBUF);
+		free(fb_dev, M_DEVBUF);
+		free(va_dev, M_DEVBUF);
 #endif
 	}
 	adapter = new_adp;
 	vidsw = new_vidsw;
 #ifdef FB_INSTALL_CDEV
 	vidcdevsw = new_cdevsw;
+	fb_dev = new_fb_dev;
+	va_dev = new_va_dev;
 #endif
 	adapters = newsize;
 	splx(s);
@@ -352,14 +367,43 @@
 #define FB_UNIT(dev)	dev2unit(dev)
 #define FB_MKMINOR(unit) (u)
 
-#if 0 /* experimental */
-static d_open_t		fbopen;
-static d_close_t	fbclose;
-static d_read_t		fbread;
-static d_write_t	fbwrite;
-static d_ioctl_t	fbioctl;
-static d_mmap_t		fbmmap;
+#if 1 /* experimental */
+static int fbopen(struct cdev *dev, int flags, int devtype, struct thread *td) {
+	int unit = FB_UNIT(dev); 	 
+	if (unit >= adapters) return ENXIO;
+	if (vidcdevsw[unit] == NULL) return ENXIO;
+	return vidcdevsw[unit]->d_open(va_dev[unit], flags, devtype, td);
+}
+
+static int fbclose(struct cdev *dev, int fflag, int devtype, struct thread *td) {
+	int unit = FB_UNIT(dev); 	 
+	if (vidcdevsw[unit] == NULL) return ENXIO;
+	return vidcdevsw[unit]->d_close(va_dev[unit], fflag, devtype, td);
+}
+
+static int fbread(struct cdev *dev, struct uio *uio, int flags) {
+	int unit = FB_UNIT(dev); 	 
+	if (vidcdevsw[unit] == NULL) return ENXIO;
+	return vidcdevsw[unit]->d_read(va_dev[unit], uio, flags);
+}
 
+static int fbwrite(struct cdev *dev, struct uio *uio, int flags) {
+	int unit = FB_UNIT(dev); 	 
+	if (vidcdevsw[unit] == NULL) return ENXIO;
+	return vidcdevsw[unit]->d_write(va_dev[unit], uio, flags);
+}
+
+static int fbioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) {
+	int unit = FB_UNIT(dev); 	 
+	if (vidcdevsw[unit] == NULL) return ENXIO;
+	return vidcdevsw[unit]->d_ioctl(va_dev[unit], cmd, data, flags, td);
+}
+
+static int fbmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr) {
+	int unit = FB_UNIT(dev); 	 
+	if (vidcdevsw[unit] == NULL) return ENXIO;
+	return vidcdevsw[unit]->d_mmap(va_dev[unit], offset, paddr, nprot, memattr);
+}
 
 static struct cdevsw fb_cdevsw = {
 	.d_version =	D_VERSION,
@@ -400,7 +444,7 @@
 DECLARE_MODULE(fb, fb_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
 
 int
-fb_attach(int unit, video_adapter_t *adp, struct cdevsw *cdevsw)
+fb_attach(int unit, video_adapter_t *adp, struct cdevsw *cdevsw, struct cdev *cdev)
 {
 	int s;
 
@@ -412,6 +456,9 @@
 	s = spltty();
 	adp->va_minor = unit;
 	vidcdevsw[adp->va_index] = cdevsw;
+	fb_dev[adp->va_index] = make_dev(&fb_cdevsw, adp->va_index, UID_ROOT,
+		GID_WHEEL, 0660, "fb%d", adp->va_index);
+	va_dev[adp->va_index] = cdev;
 	splx(s);
 
 	printf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit);
@@ -432,6 +479,9 @@
 
 	s = spltty();
 	vidcdevsw[adp->va_index] = NULL;
+	destroy_dev(fb_dev[adp->va_index]);
+	fb_dev[adp->va_index] = NULL;
+	va_dev[adp->va_index] = NULL;
 	splx(s);
 	return 0;
 }
diff -ru --exclude-from freebsd-src-diff-exclude-names /usr/src/sys/dev/fb/fbreg.h freebsd-11.1/sys/dev/fb/fbreg.h
--- /usr/src/sys/dev/fb/fbreg.h	2017-07-21 07:41:47.000000000 +0800
+++ freebsd-11.1/sys/dev/fb/fbreg.h	2020-08-06 13:36:26.949051364 +0800
@@ -303,7 +303,7 @@
 
 /* virtual frame buffer driver functions */
 int		fb_attach(int unit, video_adapter_t *adp,
-			  struct cdevsw *cdevsw);
+			  struct cdevsw *cdevsw, struct cdev *cdev);
 int		fb_detach(int unit, video_adapter_t *adp,
 			  struct cdevsw *cdevsw);
 
diff -ru --exclude-from freebsd-src-diff-exclude-names /usr/src/sys/isa/vga_isa.c freebsd-11.1/sys/isa/vga_isa.c
--- /usr/src/sys/isa/vga_isa.c	2017-07-21 07:42:12.000000000 +0800
+++ freebsd-11.1/sys/isa/vga_isa.c	2020-08-06 13:35:06.550618335 +0800
@@ -206,8 +206,11 @@
 		return (error);
 
 #ifdef FB_INSTALL_CDEV
+	/*sc->cdev*/
+	struct cdev *cdev = make_dev(&isavga_cdevsw, unit, UID_ROOT, GID_WHEEL, 0600,
+		"%s%d", sc->adp->va_name, unit);
 	/* attach a virtual frame buffer device */
-	error = fb_attach(VGA_MKMINOR(unit), sc->adp, &isavga_cdevsw);
+	error = fb_attach(VGA_MKMINOR(unit), sc->adp, &isavga_cdevsw, cdev);
 	if (error)
 		return (error);
 #endif /* FB_INSTALL_CDEV */
@@ -215,7 +218,7 @@
 	if (0 && bootverbose)
 		vidd_diag(sc->adp, bootverbose);
 
-#if 0 /* experimental */
+#if 1 /* experimental */
 	device_add_child(dev, "fb", -1);
 	bus_generic_attach(dev);
 #endif
