Subject: Better semantics for attaching /dev/fb
To: None <port-sparc@NetBSD.ORG>
From: Jason Thorpe <thorpej@SJ.Xenotropic.COM>
List: port-sparc
Date: 11/17/1995 11:24:54
After exchanging an e-mail or two with David Jones, I decided I'd peer 
into why his cgtwo was losing while I wait for the world to rebuild.  It 
appears there's a case where the framebuffer won't get attached, but then 
RASTERCONSOLE will try to print to it.  This might be the cause of the 
data fault David saw.

I fixed a couple of potential buglets in cgtwo.c and removed some 
sun4c-specific cruft not really applicable to that driver.  Also fixed a 
bogus prototype for fb_attach() (it was misnamed fbattach() in the header 
file...)

While I was there, I decided to muck about with fixing the framebuffer 
attachment semantics.  The way things are now, you could really lose if 
you have multiple framebuffers on a Sun 4.  So, I thought about this and 
came up with the following set of diffs (including the cgtwo fixes...)

Basically, what they do is (in this order):

	* Check if a framebuffer has been forcefully attached to /dev/fb.
	  If so, return.

	* If we're being forced into /dev/fb (see below), replace any
	  existing framebuffer, lock out all others, and return.

	* If we're the console, replace any existing framebuffer,
	  only allow forceful replacements, and return.

	* Attach the framebuffer, replacing any existing one, and return.

Note that every time a framebuffer is replaced, a message is displayed to 
that fact.

With these changes, one may hard-code a /dev/fb by using "flags 0x01" on 
the config line in your kernel config file, like this:

bwtwo0		at obio0 addr 0xfd000000 level 4 flags 0x01

David, I can build you a GENERIC kernel for you to try these out, if need be.

I haven't finsihed compiling these changes yet, so there might be a typo 
or two, but I figured I'd get them out there anyhow.

Ciao.

------------------------------------------------------------------------------
Jason R. Thorpe                                         thorpej@Xenotropic.COM

           Just me and my collection of obsolete computer gear(s).

-----cut here-----
Index: dev/bwtwo.c
===================================================================
RCS file: /usr/og/devsrc/netbsd/src/sys/arch/sparc/dev/bwtwo.c,v
retrieving revision 1.10
diff -c -r1.10 bwtwo.c
*** bwtwo.c	1995/11/17 10:35:03	1.10
--- bwtwo.c	1995/11/17 18:59:56
***************
*** 153,158 ****
--- 153,159 ----
  	sc->sc_fb.fb_driver = &bwtwofbdriver;
  	sc->sc_fb.fb_device = &sc->sc_dev;
  	sc->sc_fb.fb_type.fb_type = FBTYPE_SUN2BW;
+ 	sc->sc_fb.fb_flags = sc->sc_dev->dv_cfdata->cf_flags;
  
  	switch (ca->ca_bustype) {
  	case BUS_OBIO:
***************
*** 232,243 ****
  	if (sbus)
  		sbus_establish(&sc->sc_sd, &sc->sc_dev);
  #endif
- 	/*
- 	 * XXX: this could cause a panic in fb_attach() if more
- 	 * than one frame buffer device is found on a Sun 4.
- 	 */
  	if (node == fbnode || cputyp == CPU_SUN4)
! 		fb_attach(&sc->sc_fb);
  }
  
  int
--- 233,240 ----
  	if (sbus)
  		sbus_establish(&sc->sc_sd, &sc->sc_dev);
  #endif
  	if (node == fbnode || cputyp == CPU_SUN4)
! 		fb_attach(&sc->sc_fb, isconsole);
  }
  
  int
Index: dev/cgsix.c
===================================================================
RCS file: /usr/og/devsrc/netbsd/src/sys/arch/sparc/dev/cgsix.c,v
retrieving revision 1.1.1.4
diff -c -r1.1.1.4 cgsix.c
*** cgsix.c	1995/10/08 13:31:00	1.1.1.4
--- cgsix.c	1995/11/17 19:00:09
***************
*** 184,189 ****
--- 184,190 ----
  	sc->sc_fb.fb_driver = &cg6_fbdriver;
  	sc->sc_fb.fb_device = &sc->sc_dev;
  	sc->sc_fb.fb_type.fb_type = FBTYPE_SUNFAST_COLOR;
+ 	sc->sc_fb.fb_flags = sc->sc_dev->dv_cfdata->cf_flags;
  
  	switch (ca->ca_bustype) {
  	case BUS_OBIO:
***************
*** 254,260 ****
  	if (sbus)
  		sbus_establish(&sc->sc_sd, &sc->sc_dev);
  	if (node == fbnode)
! 		fb_attach(&sc->sc_fb);
  }
  
  int
--- 255,261 ----
  	if (sbus)
  		sbus_establish(&sc->sc_sd, &sc->sc_dev);
  	if (node == fbnode)
! 		fb_attach(&sc->sc_fb, isconsole);
  }
  
  int
Index: dev/cgthree.c
===================================================================
RCS file: /usr/og/devsrc/netbsd/src/sys/arch/sparc/dev/cgthree.c,v
retrieving revision 1.1.1.4
diff -c -r1.1.1.4 cgthree.c
*** cgthree.c	1995/10/08 13:31:04	1.1.1.4
--- cgthree.c	1995/11/17 19:00:26
***************
*** 149,154 ****
--- 149,155 ----
  
  	sc->sc_fb.fb_driver = &cgthreefbdriver;
  	sc->sc_fb.fb_device = &sc->sc_dev;
+ 	sc->sc_fb.fb_flags = sc->sc_dev->dv_cfdata->cf_flags;
  	/*
  	 * The defaults below match my screen, but are not guaranteed
  	 * to be correct as defaults go...
***************
*** 215,221 ****
  	if (sbus)
  		sbus_establish(&sc->sc_sd, &sc->sc_dev);
  	if (node == fbnode)
! 		fb_attach(&sc->sc_fb);
  }
  
  int
--- 216,222 ----
  	if (sbus)
  		sbus_establish(&sc->sc_sd, &sc->sc_dev);
  	if (node == fbnode)
! 		fb_attach(&sc->sc_fb, isconsole);
  }
  
  int
Index: dev/cgtwo.c
===================================================================
RCS file: /usr/og/devsrc/netbsd/src/sys/arch/sparc/dev/cgtwo.c,v
retrieving revision 1.1.1.5
diff -c -r1.1.1.5 cgtwo.c
*** cgtwo.c	1995/11/17 05:01:45	1.1.1.5
--- cgtwo.c	1995/11/17 19:02:21
***************
*** 71,82 ****
  #endif
  
  #include <machine/cgtworeg.h>
- #include <sparc/dev/sbusvar.h>
  
  /* per-display variables */
  struct cgtwo_softc {
  	struct	device sc_dev;		/* base device */
- 	struct	sbusdev sc_sd;		/* sbus device */
  	struct	fbdevice sc_fb;		/* frame buffer device */
  	caddr_t	sc_phys;		/* display RAM (phys addr) */
  	volatile struct cg2statusreg *sc_reg;	/* CG2 control registers */
--- 71,80 ----
***************
*** 158,173 ****
  	register int node, i;
  	register struct cgtwo_all *p;
  	int isconsole;
- 	int sbus = 1;
  	char *nam;
  
  	sc->sc_fb.fb_driver = &cgtwofbdriver;
  	sc->sc_fb.fb_device = &sc->sc_dev;
  	sc->sc_fb.fb_type.fb_type = FBTYPE_SUN2COLOR;
  
  	switch (ca->ca_bustype) {
  	case BUS_VME16:
! 		sbus = node = 0;
  		nam = "cgtwo";
  		break;
  
--- 156,171 ----
  	register int node, i;
  	register struct cgtwo_all *p;
  	int isconsole;
  	char *nam;
  
  	sc->sc_fb.fb_driver = &cgtwofbdriver;
  	sc->sc_fb.fb_device = &sc->sc_dev;
  	sc->sc_fb.fb_type.fb_type = FBTYPE_SUN2COLOR;
+ 	sc->sc_fb.fb_flags = sc->sc_dev->dv_cfdata->cf_flags;
  
  	switch (ca->ca_bustype) {
  	case BUS_VME16:
! 		node = 0;
  		nam = "cgtwo";
  		break;
  
***************
*** 204,213 ****
  			isconsole = 0;
  	}
  #endif
- #if defined(SUN4C) || defined(SUN4M)
- 	if (cputyp == CPU_SUN4C || cputyp == CPU_SUN4M)
- 		isconsole = node == fbnode && fbconstty != NULL;
- #endif
  	sc->sc_phys = (caddr_t)ca->ca_ra.ra_paddr;
  	if ((sc->sc_fb.fb_pixels = ca->ca_ra.ra_vaddr) == NULL && isconsole) {
  		/* this probably cannot happen, but what the heck */
--- 202,207 ----
***************
*** 236,245 ****
  #endif
  	} else
  		printf("\n");
! 	if (sbus)
! 		sbus_establish(&sc->sc_sd, &sc->sc_dev);
! 	if (node == fbnode)
! 		fb_attach(&sc->sc_fb);
  }
  
  int
--- 230,237 ----
  #endif
  	} else
  		printf("\n");
! 	if (node == fbnode || cputyp == CPU_SUN4)
! 		fb_attach(&sc->sc_fb, isconsole);
  }
  
  int
Index: dev/fb.c
===================================================================
RCS file: /usr/og/devsrc/netbsd/src/sys/arch/sparc/dev/fb.c,v
retrieving revision 1.3
diff -c -r1.3 fb.c
*** fb.c	1995/10/08 18:28:17	1.3
--- fb.c	1995/11/17 18:50:27
***************
*** 72,83 ****
  }
  
  void
! fb_attach(fb)
  	struct fbdevice *fb;
  {
  
! if (devfb) panic("multiple /dev/fb declarers");
  	devfb = fb;
  }
  
  int
--- 72,142 ----
  }
  
  void
! fb_attach(fb, isconsole)
  	struct fbdevice *fb;
+ 	int isconsole;
  {
+ 	static int no_replace, seen_force;
  
! 	/*
! 	 * We've already had a framebuffer forced into /dev/fb.  Don't
! 	 * allow any more, even if this is the console.
! 	 */
! 	if (seen_force) {
! 		if (devfb) {	/* sanity */
! 			printf("%s: /dev/fb already full\n",
! 			    fb->fb_device->dv_xname);
! 			return;
! 		} else
! 			seen_force = 0;
! 	}
! 
! 	/*
! 	 * Check to see if we're being forced into /dev/fb.
! 	 */
! 	if (fb->fb_flags & FB_FORCE) {
! 		if (devfb)
! 			printf("%s: forcefully replaced %s\n",
! 			    fb->fb_device->dv_xname,
! 			    devfb->fb_device->dv_xname);
! 		devfb = fb;
! 		seen_force = no_replace = 1;
! 		goto attached;
! 	}
! 
! 	/*
! 	 * Check to see if we're the console.  If we are, then replace
! 	 * any currently existing framebuffer.
! 	 */
! 	if (isconsole) {
! 		if (devfb)
! 			printf("%s: replaced %s\n", fb->fb_device->dv_xname,
! 			    devfb->fb_device->dv_xname);
! 		devfb = fb;
! 		no_replace = 1;
! 		goto attached;
! 	}
! 
! 	/*
! 	 * For the final case, we check to see if we can replace an
! 	 * existing framebuffer, if not, say so and return.
! 	 */
! 	if (no_replace) {
! 		if (devfb) {	/* sanity */
! 			printf("%s: /dev/fb already full\n",
! 			    fb->fb_device->dv_xname);
! 			return;
! 		} else
! 			no_replace = 0;
! 	}
! 
! 	if (devfb)
! 		printf("%s: replaced %d\n", fb->fb_device->dv_xname,
! 		    devfb->fb_device->dv_xname);
  	devfb = fb;
+ 
+  attached:
+ 	printf("%s: attached to /dev/fb\n", devfb->fb_device->dv_xname);
  }
  
  int
Index: include/fbvar.h
===================================================================
RCS file: /usr/og/devsrc/netbsd/src/sys/arch/sparc/include/fbvar.h,v
retrieving revision 1.1.1.4
diff -c -r1.1.1.4 fbvar.h
*** fbvar.h	1995/10/08 13:32:20	1.1.1.4
--- fbvar.h	1995/11/17 18:55:48
***************
*** 76,88 ****
  	struct	fbdriver *fb_driver;	/* pointer to driver */
  	struct	device *fb_device;	/* parameter for fbd_unblank */
  
  #ifdef RASTERCONSOLE
  	/* Raster console emulator state */
  	struct	rconsole fb_rcons;
  #endif
  };
  
! void	fbattach __P((struct fbdevice *));
  void	fb_setsize __P((struct fbdevice *, int, int, int, int, int));
  #ifdef RASTERCONSOLE
  void	fbrcons_init __P((struct fbdevice *));
--- 76,91 ----
  	struct	fbdriver *fb_driver;	/* pointer to driver */
  	struct	device *fb_device;	/* parameter for fbd_unblank */
  
+ 	int	fb_flags;		/* flags from config */
+ #define	FB_FORCE	0x00000001	/* force device into /dev/fb */
+ 
  #ifdef RASTERCONSOLE
  	/* Raster console emulator state */
  	struct	rconsole fb_rcons;
  #endif
  };
  
! void	fb_attach __P((struct fbdevice *, int));
  void	fb_setsize __P((struct fbdevice *, int, int, int, int, int));
  #ifdef RASTERCONSOLE
  void	fbrcons_init __P((struct fbdevice *));