Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 24 Aug 2009 10:53:30 +0000 (UTC)
From:      Ed Schouten <ed@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r196506 - in head/sys: kern sys
Message-ID:  <200908241053.n7OArUhX092666@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ed
Date: Mon Aug 24 10:53:30 2009
New Revision: 196506
URL: http://svn.freebsd.org/changeset/base/196506

Log:
  Allow multiple console devices per driver without insane code duplication.
  
  Say, a driver wants to have multiple console devices to pick from, you
  would normally write down something like this:
  
  	CONSOLE_DRIVER(dev1);
  	CONSOLE_DRIVER(dev2);
  
  Unfortunately, this means that you have to declare 10 cn routines,
  instead of 5. It also isn't possible to initialize cn_arg on beforehand.
  
  I noticed this restriction when I was implementing some of the console
  bits for my vt(4) driver in my newcons branch. I have a single set of cn
  routines (termcn_*) which are shared by all vt(4) console devices.
  
  In order to solve this, I'm adding a separate consdev_ops structure,
  which contains all the function pointers. This structure is referenced
  through consdev's cn_ops field.
  
  While there, I'm removing CONS_DRIVER() and cn_checkc, which have been
  deprecated for years. They weren't used throughout the source, until the
  Xen console driver showed up. CONSOLE_DRIVER() has been changed to do
  the right thing. It now declares both the consdev and consdev_ops
  structure and ties them together. In other words: this change doesn't
  change the KPI for drivers that used the regular way of declaring
  console devices.
  
  If drivers want to use multiple console devices, they can do this as
  follows:
  
  	static const struct consdev_ops mydriver_cnops = {
  		.cn_probe	= mydriver_cnprobe,
  		...
  	};
  	static struct mydriver_softc cons0_softc = {
  		...
  	};
  	CONSOLE_DEVICE(cons0, mydriver_cnops, &cons0_softc);
  	static struct mydriver_softc cons1_softc = {
  		...
  	};
  	CONSOLE_DEVICE(cons1, mydriver_cnops, &cons1_softc);
  
  Obtained from:	//depot/user/ed/newcons/...

Modified:
  head/sys/kern/kern_cons.c
  head/sys/sys/cons.h

Modified: head/sys/kern/kern_cons.c
==============================================================================
--- head/sys/kern/kern_cons.c	Mon Aug 24 10:16:19 2009	(r196505)
+++ head/sys/kern/kern_cons.c	Mon Aug 24 10:53:30 2009	(r196506)
@@ -124,9 +124,10 @@ cninit(void)
 	SET_FOREACH(list, cons_set) {
 		cn = *list;
 		cnremove(cn);
-		if (cn->cn_probe == NULL)
+		/* Skip cons_consdev. */
+		if (cn->cn_ops == NULL)
 			continue;
-		cn->cn_probe(cn);
+		cn->cn_ops->cn_probe(cn);
 		if (cn->cn_pri == CN_DEAD)
 			continue;
 		if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri)
@@ -135,14 +136,14 @@ cninit(void)
 			/*
 			 * Initialize console, and attach to it.
 			 */
-			cn->cn_init(cn);
+			cn->cn_ops->cn_init(cn);
 			cnadd(cn);
 		}
 	}
 	if (best_cn == NULL)
 		return;
 	if ((boothowto & RB_MULTIPLE) == 0) {
-		best_cn->cn_init(best_cn);
+		best_cn->cn_ops->cn_init(best_cn);
 		cnadd(best_cn);
 	}
 	if (boothowto & RB_PAUSE)
@@ -218,7 +219,7 @@ cnremove(struct consdev *cn)
 		 * freed after the system has initialized.
 		 */
 		if (cn->cn_term != NULL)
-			cn->cn_term(cn);
+			cn->cn_ops->cn_term(cn);
 #endif
 		return;
 	}
@@ -371,13 +372,9 @@ cncheckc(void)
 	STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
 		cn = cnd->cnd_cn;
 		if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
-			if (cn->cn_checkc != NULL)
-				c = cn->cn_checkc(cn);
-			else
-				c = cn->cn_getc(cn);
-			if (c != -1) {
+			c = cn->cn_ops->cn_getc(cn);
+			if (c != -1)
 				return (c);
-			}
 		}
 	}
 	return (-1);
@@ -396,8 +393,8 @@ cnputc(int c)
 		cn = cnd->cnd_cn;
 		if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
 			if (c == '\n')
-				cn->cn_putc(cn, '\r');
-			cn->cn_putc(cn, c);
+				cn->cn_ops->cn_putc(cn, '\r');
+			cn->cn_ops->cn_putc(cn, c);
 		}
 	}
 	if (console_pausing && c == '\n' && !kdb_active) {

Modified: head/sys/sys/cons.h
==============================================================================
--- head/sys/sys/cons.h	Mon Aug 24 10:16:19 2009	(r196505)
+++ head/sys/sys/cons.h	Mon Aug 24 10:53:30 2009	(r196506)
@@ -45,10 +45,9 @@ typedef	void	cn_probe_t(struct consdev *
 typedef	void	cn_init_t(struct consdev *);
 typedef	void	cn_term_t(struct consdev *);
 typedef	int	cn_getc_t(struct consdev *);
-typedef	int	cn_checkc_t(struct consdev *);
 typedef	void	cn_putc_t(struct consdev *, int);
 
-struct consdev {
+struct consdev_ops {
 	cn_probe_t	*cn_probe;
 				/* probe hardware and fill in consdev info */
 	cn_init_t	*cn_init;
@@ -57,10 +56,13 @@ struct consdev {
 				/* turn off as console */
 	cn_getc_t	*cn_getc;
 				/* kernel getchar interface */
-	cn_checkc_t	*cn_checkc;
-				/* kernel "return char if available" interface */
 	cn_putc_t	*cn_putc;
 				/* kernel putchar interface */
+};
+
+struct consdev {
+	const struct consdev_ops *cn_ops;
+				/* console device operations. */
 	short	cn_pri;		/* pecking order; the higher the better */
 	void	*cn_arg;	/* drivers method argument */
 	int	cn_flags;	/* capabilities of this console */
@@ -83,21 +85,22 @@ struct consdev {
 extern	struct msgbuf consmsgbuf; /* Message buffer for constty. */
 extern	struct tty *constty;	/* Temporary virtual console. */
 
-#define CONS_DRIVER(name, probe, init, term, getc, checkc, putc, dbctl)	\
-	static struct consdev name##_consdev = {			\
-		probe, init, term, getc, checkc, putc			\
+#define	CONSOLE_DEVICE(name, ops, arg)					\
+	static struct consdev name = {					\
+		.cn_ops = &ops,						\
+		.cn_arg = (arg),					\
 	};								\
-	DATA_SET(cons_set, name##_consdev)
+	DATA_SET(cons_set, name)
 
-#define CONSOLE_DRIVER(name)						\
-	static struct consdev name##_consdev = {			\
+#define	CONSOLE_DRIVER(name)						\
+	static const struct consdev_ops name##_consdev_ops = {		\
 		.cn_probe = name##_cnprobe,				\
 		.cn_init = name##_cninit,				\
 		.cn_term = name##_cnterm,				\
 		.cn_getc = name##_cngetc,				\
 		.cn_putc = name##_cnputc,				\
 	};								\
-	DATA_SET(cons_set, name##_consdev)
+	CONSOLE_DEVICE(name##_consdev, name##_consdev_ops, NULL)
 
 /* Other kernel entry points. */
 void	cninit(void);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908241053.n7OArUhX092666>