Subject: kern/1289: cdev_fb_init() breaks Xserver on DEC framebuffers
To: None <gnats-bugs@gnats.netbsd.org>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: netbsd-bugs
Date: 07/27/1995 14:56:17
>Number:         1289
>Category:       kern
>Synopsis:       cdevsw macro for frame-buffers insufficently general
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jul 27 18:05:04 1995
>Last-Modified:
>Originator:     Jonathan Stone
>Organization:
	
>Release:        NetBSD-current as at (or near) 24 July 1995.
>Environment:
	
System: NetBSD Reno.Stanford.EDU 1.0A NetBSD 1.0A (CURRENT) #420: Tue Jul 25 16:50:58 PDT 1995 jonathan@Reno.Stanford.EDU:/usr/src/sys/arch/pmax/compile/CURRENT pmax


>Description:
	The file /usr/src/sys/sys/conf.h has a macro, cdev_fb_init(),
	which   purports to initalize entries for framebuffers in a
	struct cdevsw.   This macro sets the ``select'' entry to
	enodev.  This is not adequate for DEC framebuffers (on pmax,
	vax, and alpha, from QVSS onward) which use a shared-memory queue
	for mouse and keyboard events. This buffer is shared by
	the kernel and whatever application has the framebuffer mapped
	into user-space. (The kernel updates the position of a pointer
	sprite, asynchronously with whatever the application does.)
	These systems use select() on a framebuffer to notify an application
	(the X server) that new events have been placed in the shared-memory
	 queue.

	Lack of a select() entry causes X servers for DEC framebuffers 
	to busy-wait, causing 95% to 100% system load.

	The cdev_fb_init() macro (or some variant of it) should really be
	general enough to support framebuffers on all NetBSD platforms.
	Currently, it clearly isn't.

>How-To-Repeat:
	Build a NetBSD/pmax kernel.  Add entries in the cdevsw
	for a framebuffer, using cdev_fb_init().  Start a NetBSD/pmax X11R5
	server (available at ftp://ftp.unit.no/pub/NetBSD/arch/pmax/X11R5/)
	Watch the system time (as shown by top) hit 100%.
	(Don't do this, it causes awful interactive response.)

>Fix:
	Change the cdev_init_fb() macro to cause a select routine,
	and update its current clients to provide a null select routine.

The following works as a gross hack for the pmax.
I haven't committed it because I think that the right place for the
initializatio macro is sys/sys/conf.h, not arch/pmax/pmax/conf.h.
(It may be that two macros, one with a select entry and one without,
 is a better solution; I'm agnostic on that.)



*** conf.c.DIST	Tue Jul  4 23:55:14 1995
--- conf.c	Mon Jul 24 10:26:05 1995
***************
*** 115,121 ****
--- 115,140 ----
  cdev_decl(rcons);
  #include "fb.h"
  cdev_decl(fb);
+ #include "pm.h"
+ cdev_decl(pm);
+ #include "cfb.h"
+ cdev_decl(cfb);
+ #include "xcfb.h"
+ cdev_decl(xcfb);
+ #include "mfb.h"
+ cdev_decl(mfb);
  
+ 
+ /* a framebuffer with an attached mouse: */
+ /* open, close, ioctl, mmap */
+ 
+ #define	cdev_fbm_init(c,n) { \
+ 	dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ 	(dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ 	(dev_type_stop((*))) enodev, 0, dev_init(c,n,select), \
+ 	dev_init(c,n,mmap) }
+ 
+ 
  struct cdevsw	cdevsw[] =
  {
  	cdev_cn_init(1,cn),		/* 0: virtual console */
***************
*** 126,142 ****
          cdev_ptc_init(NPTY,ptc),        /* 5: pseudo-tty master */
  	cdev_log_init(1,log),		/* 6: /dev/klog */
  	cdev_fd_init(1,fd),		/* 7: file descriptor pseudo-dev */
! 	cdev_notdef(),			/* 8: 2100/3100 frame buffer */
  	cdev_notdef(),			/* 9: old slot for SCSI disk */
  	cdev_tape_init(NTZ,tz),		/* 10: SCSI tape */
  	cdev_disk_init(NVND,vnd),	/* 11: vnode disk driver */
  	cdev_bpftun_init(NBPFILTER,bpf),/* 12: Berkeley packet filter */
! 	cdev_notdef(),			/* 13: color frame buffer */
! 	cdev_notdef(),			/* 14: maxine color frame buffer */
  	cdev_tty_init(NDTOP,dtop),	/* 15: desktop bus interface */
  	cdev_tty_init(NDC,dc),		/* 16: dc7085 serial interface */
  	cdev_tty_init(NSCC,scc),	/* 17: scc 82530 serial interface */
! 	cdev_notdef(),			/* 18: mono frame buffer */
          cdev_notdef(),		        /* 19: mt */
  	cdev_tty_init(NPTY,pts),	/* 20: pty slave  */
          cdev_ptc_init(NPTY,ptc),        /* 21: pty master */
--- 145,161 ----
          cdev_ptc_init(NPTY,ptc),        /* 5: pseudo-tty master */
  	cdev_log_init(1,log),		/* 6: /dev/klog */
  	cdev_fd_init(1,fd),		/* 7: file descriptor pseudo-dev */
! 	cdev_fbm_init(NPM,pm),		/* 8: 2100/3100 frame buffer */
  	cdev_notdef(),			/* 9: old slot for SCSI disk */
  	cdev_tape_init(NTZ,tz),		/* 10: SCSI tape */
  	cdev_disk_init(NVND,vnd),	/* 11: vnode disk driver */
  	cdev_bpftun_init(NBPFILTER,bpf),/* 12: Berkeley packet filter */
! 	cdev_fbm_init(NCFB,cfb),	/* 13: color frame buffer */
! 	cdev_fbm_init(NXCFB,xcfb),	/* 14: maxine color frame buffer */
  	cdev_tty_init(NDTOP,dtop),	/* 15: desktop bus interface */
  	cdev_tty_init(NDC,dc),		/* 16: dc7085 serial interface */
  	cdev_tty_init(NSCC,scc),	/* 17: scc 82530 serial interface */
! 	cdev_fbm_init(NMFB,mfb),	/* 18: mono frame buffer */
          cdev_notdef(),		        /* 19: mt */
  	cdev_tty_init(NPTY,pts),	/* 20: pty slave  */
          cdev_ptc_init(NPTY,ptc),        /* 21: pty master */
***************
*** 206,212 ****
  	cdev_notdef(),		/* 83: fd */
  	cdev_notdef(),		/* 84: DTi */
  	cdev_tty_init(NRCONS,rcons),	/* 85: raster console pseudo-device */
! 	cdev_fb_init(NFB,fb),	/* 86: frame buffer pseudo-device */
  };
  int	nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
  
--- 225,231 ----
  	cdev_notdef(),		/* 83: fd */
  	cdev_notdef(),		/* 84: DTi */
  	cdev_tty_init(NRCONS,rcons),	/* 85: raster console pseudo-device */
! 	cdev_fbm_init(NFB,fb),	/* 86: frame buffer pseudo-device */
  };
  int	nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
  
>Audit-Trail:
>Unformatted: