diff options
author | ed <ed@FreeBSD.org> | 2009-08-24 10:53:30 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2009-08-24 10:53:30 +0000 |
commit | 7669d1f2c12de4c0b0410af8a8928836498760e1 (patch) | |
tree | 277706037ddf24145cff13db7a5e4cc8a1c31a7d /sys/kern/kern_cons.c | |
parent | 927d43d57415185dd776a3a857e6ae3d302a86ab (diff) | |
download | FreeBSD-src-7669d1f2c12de4c0b0410af8a8928836498760e1.zip FreeBSD-src-7669d1f2c12de4c0b0410af8a8928836498760e1.tar.gz |
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/...
Diffstat (limited to 'sys/kern/kern_cons.c')
-rw-r--r-- | sys/kern/kern_cons.c | 23 |
1 files changed, 10 insertions, 13 deletions
diff --git a/sys/kern/kern_cons.c b/sys/kern/kern_cons.c index 31df2e8..2b9854f 100644 --- a/sys/kern/kern_cons.c +++ b/sys/kern/kern_cons.c @@ -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) { |