svn commit: r184535 - in user/imp/newcard/sys: . conf dev/adb kern modules/rl pci sys

Warner Losh imp at FreeBSD.org
Sat Nov 1 14:49:33 PDT 2008


Author: imp
Date: Sat Nov  1 21:49:32 2008
New Revision: 184535
URL: http://svn.freebsd.org/changeset/base/184535

Log:
  r184514 through r184524

Added:
  user/imp/newcard/sys/kern/kern_cons.c
     - copied unchanged from r184524, head/sys/kern/kern_cons.c
Deleted:
  user/imp/newcard/sys/kern/tty_cons.c
Modified:
  user/imp/newcard/sys/   (props changed)
  user/imp/newcard/sys/conf/NOTES
  user/imp/newcard/sys/conf/files
  user/imp/newcard/sys/conf/options
  user/imp/newcard/sys/dev/adb/adb_mouse.c
  user/imp/newcard/sys/kern/tty.c
  user/imp/newcard/sys/modules/rl/Makefile
  user/imp/newcard/sys/pci/if_rl.c
  user/imp/newcard/sys/pci/if_rlreg.h
  user/imp/newcard/sys/sys/tty.h

Modified: user/imp/newcard/sys/conf/NOTES
==============================================================================
--- user/imp/newcard/sys/conf/NOTES	Sat Nov  1 21:16:09 2008	(r184534)
+++ user/imp/newcard/sys/conf/NOTES	Sat Nov  1 21:49:32 2008	(r184535)
@@ -1875,6 +1875,7 @@ device		my		# Myson Fast Ethernet (MTD80
 device		nge		# NatSemi DP83820 gigabit Ethernet
 device		re		# RealTek 8139C+/8169/8169S/8110S
 device		rl		# RealTek 8129/8139
+options 	RL_TWISTER_ENABLE # Enable long cable compensation code
 device		pcn		# AMD Am79C97x PCI 10/100 NICs
 device		sf		# Adaptec AIC-6915 (``Starfire'')
 device		sis		# Silicon Integrated Systems SiS 900/SiS 7016

Modified: user/imp/newcard/sys/conf/files
==============================================================================
--- user/imp/newcard/sys/conf/files	Sat Nov  1 21:16:09 2008	(r184534)
+++ user/imp/newcard/sys/conf/files	Sat Nov  1 21:49:32 2008	(r184535)
@@ -1596,6 +1596,7 @@ kern/kern_alq.c			optional alq
 kern/kern_clock.c		standard
 kern/kern_condvar.c		standard
 kern/kern_conf.c		standard
+kern/kern_cons.c		standard
 kern/kern_cpu.c			standard
 kern/kern_cpuset.c		standard
 kern/kern_context.c		standard
@@ -1708,7 +1709,6 @@ kern/sysv_sem.c			optional sysvsem
 kern/sysv_shm.c			optional sysvshm
 kern/tty.c			standard
 kern/tty_compat.c		optional compat_43tty
-kern/tty_cons.c			standard
 kern/tty_info.c			standard
 kern/tty_inq.c			standard
 kern/tty_outq.c			standard

Modified: user/imp/newcard/sys/conf/options
==============================================================================
--- user/imp/newcard/sys/conf/options	Sat Nov  1 21:16:09 2008	(r184534)
+++ user/imp/newcard/sys/conf/options	Sat Nov  1 21:49:32 2008	(r184535)
@@ -672,6 +672,9 @@ ED_SIC			opt_ed.h
 # bce driver
 BCE_DEBUG		opt_bce.h
 
+# rl driver
+RL_TWISTER_ENABLE	opt_rl.h
+
 SOCKBUF_DEBUG		opt_global.h
 
 # options for ubsec driver

Modified: user/imp/newcard/sys/dev/adb/adb_mouse.c
==============================================================================
--- user/imp/newcard/sys/dev/adb/adb_mouse.c	Sat Nov  1 21:16:09 2008	(r184534)
+++ user/imp/newcard/sys/dev/adb/adb_mouse.c	Sat Nov  1 21:49:32 2008	(r184535)
@@ -382,6 +382,7 @@ ams_read(struct cdev *dev, struct uio *u
 	struct adb_mouse_softc *sc;
 	size_t len;
 	int8_t outpacket[8];
+	int error;
 
 	sc = CDEV_GET_SOFTC(dev);
 	if (sc == NULL)
@@ -403,7 +404,11 @@ ams_read(struct cdev *dev, struct uio *u
 
 	
 			/* Otherwise, block on new data */
-			cv_wait(&sc->sc_cv,&sc->sc_mtx);
+			error = cv_wait_sig(&sc->sc_cv, &sc->sc_mtx);
+			if (error) {
+				mtx_unlock(&sc->sc_mtx);
+				return (error);
+			}
 		}
 
 		sc->packet[0] = 1 << 7;

Copied: user/imp/newcard/sys/kern/kern_cons.c (from r184524, head/sys/kern/kern_cons.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/imp/newcard/sys/kern/kern_cons.c	Sat Nov  1 21:49:32 2008	(r184535, copy of r184524, head/sys/kern/kern_cons.c)
@@ -0,0 +1,566 @@
+/*-
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: @(#)cons.c	7.2 (Berkeley) 5/9/91
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/fcntl.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/msgbuf.h>
+#include <sys/namei.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/reboot.h>
+#include <sys/sysctl.h>
+#include <sys/sbuf.h>
+#include <sys/tty.h>
+#include <sys/uio.h>
+#include <sys/vnode.h>
+
+#include <ddb/ddb.h>
+
+#include <machine/cpu.h>
+#include <machine/clock.h>
+
+static MALLOC_DEFINE(M_TTYCONS, "tty console", "tty console handling");
+
+struct cn_device {
+	STAILQ_ENTRY(cn_device) cnd_next;
+	struct		consdev *cnd_cn;
+};
+
+#define CNDEVPATHMAX	32
+#define CNDEVTAB_SIZE	4
+static struct cn_device cn_devtab[CNDEVTAB_SIZE];
+static STAILQ_HEAD(, cn_device) cn_devlist =
+    STAILQ_HEAD_INITIALIZER(cn_devlist);
+
+int	cons_avail_mask = 0;	/* Bit mask. Each registered low level console
+				 * which is currently unavailable for inpit
+				 * (i.e., if it is in graphics mode) will have
+				 * this bit cleared.
+				 */
+static int cn_mute;
+static char *consbuf;			/* buffer used by `consmsgbuf' */
+static struct callout conscallout;	/* callout for outputting to constty */
+struct msgbuf consmsgbuf;		/* message buffer for console tty */
+static u_char console_pausing;		/* pause after each line during probe */
+static char *console_pausestr=
+"<pause; press any key to proceed to next line or '.' to end pause mode>";
+struct tty *constty;			/* pointer to console "window" tty */
+static struct mtx cnputs_mtx;		/* Mutex for cnputs(). */
+static int use_cnputs_mtx = 0;		/* != 0 if cnputs_mtx locking reqd. */
+
+static void constty_timeout(void *arg);
+
+static struct consdev cons_consdev;
+DATA_SET(cons_set, cons_consdev);
+SET_DECLARE(cons_set, struct consdev);
+
+void
+cninit(void)
+{
+	struct consdev *best_cn, *cn, **list;
+
+	/*
+	 * Check if we should mute the console (for security reasons perhaps)
+	 * It can be changes dynamically using sysctl kern.consmute
+	 * once we are up and going.
+	 * 
+	 */
+        cn_mute = ((boothowto & (RB_MUTE
+			|RB_SINGLE
+			|RB_VERBOSE
+			|RB_ASKNAME)) == RB_MUTE);
+
+	/*
+	 * Find the first console with the highest priority.
+	 */
+	best_cn = NULL;
+	SET_FOREACH(list, cons_set) {
+		cn = *list;
+		cnremove(cn);
+		if (cn->cn_probe == NULL)
+			continue;
+		cn->cn_probe(cn);
+		if (cn->cn_pri == CN_DEAD)
+			continue;
+		if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri)
+			best_cn = cn;
+		if (boothowto & RB_MULTIPLE) {
+			/*
+			 * Initialize console, and attach to it.
+			 */
+			cn->cn_init(cn);
+			cnadd(cn);
+		}
+	}
+	if (best_cn == NULL)
+		return;
+	if ((boothowto & RB_MULTIPLE) == 0) {
+		best_cn->cn_init(best_cn);
+		cnadd(best_cn);
+	}
+	if (boothowto & RB_PAUSE)
+		console_pausing = 1;
+	/*
+	 * Make the best console the preferred console.
+	 */
+	cnselect(best_cn);
+}
+
+void
+cninit_finish()
+{
+	console_pausing = 0;
+} 
+
+/* add a new physical console to back the virtual console */
+int
+cnadd(struct consdev *cn)
+{
+	struct cn_device *cnd;
+	int i;
+
+	STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
+		if (cnd->cnd_cn == cn)
+			return (0);
+	for (i = 0; i < CNDEVTAB_SIZE; i++) {
+		cnd = &cn_devtab[i];
+		if (cnd->cnd_cn == NULL)
+			break;
+	}
+	if (cnd->cnd_cn != NULL)
+		return (ENOMEM);
+	cnd->cnd_cn = cn;
+	if (cn->cn_name[0] == '\0') {
+		/* XXX: it is unclear if/where this print might output */
+		printf("WARNING: console at %p has no name\n", cn);
+	}
+	STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next);
+	if (STAILQ_FIRST(&cn_devlist) == cnd)
+		ttyconsdev_select(cnd->cnd_cn->cn_name);
+
+	/* Add device to the active mask. */
+	cnavailable(cn, (cn->cn_flags & CN_FLAG_NOAVAIL) == 0);
+
+	return (0);
+}
+
+void
+cnremove(struct consdev *cn)
+{
+	struct cn_device *cnd;
+	int i;
+
+	STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
+		if (cnd->cnd_cn != cn)
+			continue;
+		if (STAILQ_FIRST(&cn_devlist) == cnd)
+			ttyconsdev_select(NULL);
+		STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next);
+		cnd->cnd_cn = NULL;
+
+		/* Remove this device from available mask. */
+		for (i = 0; i < CNDEVTAB_SIZE; i++) 
+			if (cnd == &cn_devtab[i]) {
+				cons_avail_mask &= ~(1 << i);
+				break;
+			}
+#if 0
+		/*
+		 * XXX
+		 * syscons gets really confused if console resources are
+		 * freed after the system has initialized.
+		 */
+		if (cn->cn_term != NULL)
+			cn->cn_term(cn);
+#endif
+		return;
+	}
+}
+
+void
+cnselect(struct consdev *cn)
+{
+	struct cn_device *cnd;
+
+	STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
+		if (cnd->cnd_cn != cn)
+			continue;
+		if (cnd == STAILQ_FIRST(&cn_devlist))
+			return;
+		STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next);
+		STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next);
+		ttyconsdev_select(cnd->cnd_cn->cn_name);
+		return;
+	}
+}
+
+void
+cnavailable(struct consdev *cn, int available)
+{
+	int i;
+
+	for (i = 0; i < CNDEVTAB_SIZE; i++) {
+		if (cn_devtab[i].cnd_cn == cn)
+			break;
+	}
+	if (available) {
+		if (i < CNDEVTAB_SIZE)
+			cons_avail_mask |= (1 << i); 
+		cn->cn_flags &= ~CN_FLAG_NOAVAIL;
+	} else {
+		if (i < CNDEVTAB_SIZE)
+			cons_avail_mask &= ~(1 << i);
+		cn->cn_flags |= CN_FLAG_NOAVAIL;
+	}
+}
+
+int
+cnunavailable(void)
+{
+
+	return (cons_avail_mask == 0);
+}
+
+/*
+ * sysctl_kern_console() provides output parseable in conscontrol(1).
+ */
+static int
+sysctl_kern_console(SYSCTL_HANDLER_ARGS)
+{
+	struct cn_device *cnd;
+	struct consdev *cp, **list;
+	char *p;
+	int delete, error;
+	struct sbuf *sb;
+
+	sb = sbuf_new(NULL, NULL, CNDEVPATHMAX * 2, SBUF_AUTOEXTEND);
+	if (sb == NULL)
+		return (ENOMEM);
+	sbuf_clear(sb);
+	STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
+		sbuf_printf(sb, "%s,", cnd->cnd_cn->cn_name);
+	sbuf_printf(sb, "/");
+	SET_FOREACH(list, cons_set) {
+		cp = *list;
+		if (cp->cn_name[0] != '\0')
+			sbuf_printf(sb, "%s,", cp->cn_name);
+	}
+	sbuf_finish(sb);
+	error = sysctl_handle_string(oidp, sbuf_data(sb), sbuf_len(sb), req);
+	if (error == 0 && req->newptr != NULL) {
+		p = sbuf_data(sb);
+		error = ENXIO;
+		delete = 0;
+		if (*p == '-') {
+			delete = 1;
+			p++;
+		}
+		SET_FOREACH(list, cons_set) {
+			cp = *list;
+			if (strcmp(p, cp->cn_name) != 0)
+				continue;
+			if (delete) {
+				cnremove(cp);
+				error = 0;
+			} else {
+				error = cnadd(cp);
+				if (error == 0)
+					cnselect(cp);
+			}
+			break;
+		}
+	}
+	sbuf_delete(sb);
+	return (error);
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW,
+	0, 0, sysctl_kern_console, "A", "Console device control");
+
+/*
+ * User has changed the state of the console muting.
+ * This may require us to open or close the device in question.
+ */
+static int
+sysctl_kern_consmute(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+	int ocn_mute;
+
+	ocn_mute = cn_mute;
+	error = sysctl_handle_int(oidp, &cn_mute, 0, req);
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+	return (error);
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW,
+	0, sizeof(cn_mute), sysctl_kern_consmute, "I", "");
+
+/*
+ * Low level console routines.
+ */
+int
+cngetc(void)
+{
+	int c;
+
+	if (cn_mute)
+		return (-1);
+	while ((c = cncheckc()) == -1)
+		;
+	if (c == '\r')
+		c = '\n';		/* console input is always ICRNL */
+	return (c);
+}
+
+int
+cncheckc(void)
+{
+	struct cn_device *cnd;
+	struct consdev *cn;
+	int c;
+
+	if (cn_mute)
+		return (-1);
+	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) {
+				return (c);
+			}
+		}
+	}
+	return (-1);
+}
+
+void
+cnputc(int c)
+{
+	struct cn_device *cnd;
+	struct consdev *cn;
+	char *cp;
+
+	if (cn_mute || c == '\0')
+		return;
+	STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
+		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);
+		}
+	}
+	if (console_pausing && c == '\n' && !kdb_active) {
+		for (cp = console_pausestr; *cp != '\0'; cp++)
+			cnputc(*cp);
+		if (cngetc() == '.')
+			console_pausing = 0;
+		cnputc('\r');
+		for (cp = console_pausestr; *cp != '\0'; cp++)
+			cnputc(' ');
+		cnputc('\r');
+	}
+}
+
+void
+cnputs(char *p)
+{
+	int c;
+	int unlock_reqd = 0;
+
+	if (use_cnputs_mtx) {
+		mtx_lock_spin(&cnputs_mtx);
+		unlock_reqd = 1;
+	}
+
+	while ((c = *p++) != '\0')
+		cnputc(c);
+
+	if (unlock_reqd)
+		mtx_unlock_spin(&cnputs_mtx);
+}
+
+static int consmsgbuf_size = 8192;
+SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0,
+    "");
+
+/*
+ * Redirect console output to a tty.
+ */
+void
+constty_set(struct tty *tp)
+{
+	int size;
+
+	KASSERT(tp != NULL, ("constty_set: NULL tp"));
+	if (consbuf == NULL) {
+		size = consmsgbuf_size;
+		consbuf = malloc(size, M_TTYCONS, M_WAITOK);
+		msgbuf_init(&consmsgbuf, consbuf, size);
+		callout_init(&conscallout, 0);
+	}
+	constty = tp;
+	constty_timeout(NULL);
+}
+
+/*
+ * Disable console redirection to a tty.
+ */
+void
+constty_clear(void)
+{
+	int c;
+
+	constty = NULL;
+	if (consbuf == NULL)
+		return;
+	callout_stop(&conscallout);
+	while ((c = msgbuf_getchar(&consmsgbuf)) != -1)
+		cnputc(c);
+	free(consbuf, M_TTYCONS);
+	consbuf = NULL;
+}
+
+/* Times per second to check for pending console tty messages. */
+static int constty_wakeups_per_second = 5;
+SYSCTL_INT(_kern, OID_AUTO, constty_wakeups_per_second, CTLFLAG_RW,
+    &constty_wakeups_per_second, 0, "");
+
+static void
+constty_timeout(void *arg)
+{
+	int c;
+
+	if (constty != NULL) {
+		tty_lock(constty);
+		while ((c = msgbuf_getchar(&consmsgbuf)) != -1) {
+			if (tty_putchar(constty, c) < 0) {
+				tty_unlock(constty);
+				constty = NULL;
+				break;
+			}
+		}
+
+		if (constty != NULL)
+			tty_unlock(constty);
+	}
+	if (constty != NULL) {
+		callout_reset(&conscallout, hz / constty_wakeups_per_second,
+		    constty_timeout, NULL);
+	} else {
+		/* Deallocate the constty buffer memory. */
+		constty_clear();
+	}
+}
+
+static void
+cn_drvinit(void *unused)
+{
+
+	mtx_init(&cnputs_mtx, "cnputs_mtx", NULL, MTX_SPIN | MTX_NOWITNESS);
+	use_cnputs_mtx = 1;
+}
+
+SYSINIT(cndev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, cn_drvinit, NULL);
+
+/*
+ * Sysbeep(), if we have hardware for it
+ */
+
+#ifdef HAS_TIMER_SPKR
+
+static int beeping;
+
+static void
+sysbeepstop(void *chan)
+{
+
+	timer_spkr_release();
+	beeping = 0;
+}
+
+int
+sysbeep(int pitch, int period)
+{
+
+	if (timer_spkr_acquire()) {
+		if (!beeping) {
+			/* Something else owns it. */
+			return (EBUSY);
+		}
+	}
+	timer_spkr_setfreq(pitch);
+	if (!beeping) {
+		beeping = period;
+		timeout(sysbeepstop, (void *)NULL, period);
+	}
+	return (0);
+}
+
+#else
+
+/*
+ * No hardware, no sound
+ */
+
+int
+sysbeep(int pitch __unused, int period __unused)
+{
+
+	return (ENODEV);
+}
+
+#endif
+

Modified: user/imp/newcard/sys/kern/tty.c
==============================================================================
--- user/imp/newcard/sys/kern/tty.c	Sat Nov  1 21:16:09 2008	(r184534)
+++ user/imp/newcard/sys/kern/tty.c	Sat Nov  1 21:49:32 2008	(r184535)
@@ -73,6 +73,10 @@ static struct sx tty_list_sx;
 SX_SYSINIT(tty_list, &tty_list_sx, "tty list");
 static unsigned int tty_list_count = 0;
 
+/* Character device of /dev/console. */
+static struct cdev	*dev_console;
+static const char	*dev_console_filename;
+
 /*
  * Flags that are supported and stored by this implementation.
  */
@@ -86,7 +90,7 @@ static unsigned int tty_list_count = 0;
 			HUPCL|CLOCAL|CCTS_OFLOW|CRTS_IFLOW|CDTR_IFLOW|\
 			CDSR_OFLOW|CCAR_OFLOW)
 
-#define TTY_CALLOUT(tp,d) ((tp)->t_dev != (d))
+#define	TTY_CALLOUT(tp,d) ((d) != (tp)->t_dev && (d) != dev_console)
 
 /*
  * Set TTY buffer sizes.
@@ -1189,11 +1193,7 @@ tty_wait(struct tty *tp, struct cv *cv)
 	int error;
 	int revokecnt = tp->t_revokecnt;
 
-#if 0
-	/* XXX: /dev/console also picks up Giant. */
 	tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
-#endif
-	tty_lock_assert(tp, MA_OWNED);
 	MPASS(!tty_gone(tp));
 
 	error = cv_wait_sig(cv, tp->t_mtx);
@@ -1215,11 +1215,7 @@ tty_timedwait(struct tty *tp, struct cv 
 	int error;
 	int revokecnt = tp->t_revokecnt;
 
-#if 0
-	/* XXX: /dev/console also picks up Giant. */
 	tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
-#endif
-	tty_lock_assert(tp, MA_OWNED);
 	MPASS(!tty_gone(tp));
 
 	error = cv_timedwait_sig(cv, tp->t_mtx, hz);
@@ -1662,6 +1658,10 @@ tty_hiwat_in_unblock(struct tty *tp)
 		ttydevsw_inwakeup(tp);
 }
 
+/*
+ * TTY hooks interface.
+ */
+
 static int
 ttyhook_defrint(struct tty *tp, char c, int flags)
 {
@@ -1745,6 +1745,84 @@ ttyhook_unregister(struct tty *tp)
 	tty_rel_free(tp);
 }
 
+/*
+ * /dev/console handling.
+ */
+
+static int
+ttyconsdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+	struct tty *tp;
+
+	/* System has no console device. */
+	if (dev_console_filename == NULL)
+		return (ENXIO);
+
+	/* Look up corresponding TTY by device name. */
+	sx_slock(&tty_list_sx);
+	TAILQ_FOREACH(tp, &tty_list, t_list) {
+		if (strcmp(dev_console_filename, tty_devname(tp)) == 0) {
+			dev_console->si_drv1 = tp;
+			break;
+		}
+	}
+	sx_sunlock(&tty_list_sx);
+
+	/* System console has no TTY associated. */
+	if (dev_console->si_drv1 == NULL)
+		return (ENXIO);
+	
+	return (ttydev_open(dev, oflags, devtype, td));
+}
+
+static int
+ttyconsdev_write(struct cdev *dev, struct uio *uio, int ioflag)
+{
+
+	log_console(uio);
+
+	return (ttydev_write(dev, uio, ioflag));
+}
+
+/*
+ * /dev/console is a little different than normal TTY's. Unlike regular
+ * TTY device nodes, this device node will not revoke the entire TTY
+ * upon closure and all data written to it will be logged.
+ */
+static struct cdevsw ttyconsdev_cdevsw = {
+	.d_version	= D_VERSION,
+	.d_open		= ttyconsdev_open,
+	.d_read		= ttydev_read,
+	.d_write	= ttyconsdev_write,
+	.d_ioctl	= ttydev_ioctl,
+	.d_kqfilter	= ttydev_kqfilter,
+	.d_poll		= ttydev_poll,
+	.d_mmap		= ttydev_mmap,
+	.d_name		= "ttyconsdev",
+	.d_flags	= D_TTY,
+};
+
+static void
+ttyconsdev_init(void *unused)
+{
+
+	dev_console = make_dev(&ttyconsdev_cdevsw, 0, UID_ROOT, GID_WHEEL,
+	    0600, "console");
+}
+
+SYSINIT(tty, SI_SUB_DRIVERS, SI_ORDER_FIRST, ttyconsdev_init, NULL);
+
+void
+ttyconsdev_select(const char *name)
+{
+
+	dev_console_filename = name;
+}
+
+/*
+ * Debugging routines.
+ */
+
 #include "opt_ddb.h"
 #ifdef DDB
 #include <ddb/ddb.h>
@@ -1929,7 +2007,7 @@ DB_SHOW_ALL_COMMAND(ttys, db_show_all_tt
 		    osiz,
 		    tp->t_outq.to_end - tp->t_outq.to_begin,
 		    osiz - tp->t_outlow,
-		    tp->t_column,
+		    MIN(tp->t_column, 99999),
 		    tp->t_session ? tp->t_session->s_sid : 0,
 		    tp->t_pgrp ? tp->t_pgrp->pg_id : 0);
 

Modified: user/imp/newcard/sys/modules/rl/Makefile
==============================================================================
--- user/imp/newcard/sys/modules/rl/Makefile	Sat Nov  1 21:16:09 2008	(r184534)
+++ user/imp/newcard/sys/modules/rl/Makefile	Sat Nov  1 21:49:32 2008	(r184535)
@@ -3,7 +3,7 @@
 .PATH: ${.CURDIR}/../../pci
 
 KMOD=	if_rl
-SRCS=	if_rl.c device_if.h bus_if.h pci_if.h
+SRCS=	if_rl.c device_if.h bus_if.h pci_if.h opt_rl.h
 SRCS+=	miibus_if.h
 
 .include <bsd.kmod.mk>

Modified: user/imp/newcard/sys/pci/if_rl.c
==============================================================================
--- user/imp/newcard/sys/pci/if_rl.c	Sat Nov  1 21:16:09 2008	(r184534)
+++ user/imp/newcard/sys/pci/if_rl.c	Sat Nov  1 21:49:32 2008	(r184535)
@@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
 
 #ifdef HAVE_KERNEL_OPTION_HEADERS
 #include "opt_device_polling.h"
+#include "opt_rl.h"
 #endif
 
 #include <sys/param.h>
@@ -155,7 +156,7 @@ static struct rl_type rl_devs[] = {
 	{ DELTA_VENDORID, DELTA_DEVICEID_8139, RL_8139,
 		"Delta Electronics 8139 10/100BaseTX" },
 	{ ADDTRON_VENDORID, ADDTRON_DEVICEID_8139, RL_8139,
-		"Addtron Technolgy 8139 10/100BaseTX" },
+		"Addtron Technology 8139 10/100BaseTX" },
 	{ DLINK_VENDORID, DLINK_DEVICEID_530TXPLUS, RL_8139,
 		"D-Link DFE-530TX+ 10/100BaseTX" },
 	{ DLINK_VENDORID, DLINK_DEVICEID_690TXD, RL_8139,
@@ -1318,7 +1319,7 @@ rl_rxeof(struct rl_softc *sc)
 		RL_LOCK(sc);
 	}
 
-	/* No need to sync Rx memory block as we didn't mofify it. */
+	/* No need to sync Rx memory block as we didn't modify it. */
 }
 
 /*
@@ -1383,19 +1384,143 @@ rl_txeof(struct rl_softc *sc)
 		sc->rl_watchdog_timer = 0;
 }
 
+#ifdef RL_TWISTER_ENABLE
+static void
+rl_twister_update(struct rl_softc *sc)
+{
+	uint16_t linktest;
+	/*
+	 * Table provided by RealTek (Kinston <shangh at realtek.com.tw>) for
+	 * Linux driver.  Values undocumented otherwise.
+	 */
+	static const uint32_t param[4][4] = {
+		{0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43},
+		{0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
+		{0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
+		{0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}
+	};
+
+	/*
+	 * Tune the so-called twister registers of the RTL8139.  These
+	 * are used to compensate for impedance mismatches.  The
+	 * method for tuning these registers is undocumented and the
+	 * following procedure is collected from public sources.
+	 */
+	switch (sc->rl_twister)
+	{
+	case CHK_LINK:
+		/*
+		 * If we have a sufficient link, then we can proceed in
+		 * the state machine to the next stage.  If not, then
+		 * disable further tuning after writing sane defaults.
+		 */
+		if (CSR_READ_2(sc, RL_CSCFG) & RL_CSCFG_LINK_OK) {
+			CSR_WRITE_2(sc, RL_CSCFG, RL_CSCFG_LINK_DOWN_OFF_CMD);
+			sc->rl_twister = FIND_ROW;
+		} else {
+			CSR_WRITE_2(sc, RL_CSCFG, RL_CSCFG_LINK_DOWN_CMD);
+			CSR_WRITE_4(sc, RL_NWAYTST, RL_NWAYTST_CBL_TEST);
+			CSR_WRITE_4(sc, RL_PARA78, RL_PARA78_DEF);
+			CSR_WRITE_4(sc, RL_PARA7C, RL_PARA7C_DEF);
+			sc->rl_twister = DONE;
+		}
+		break;
+	case FIND_ROW:
+		/*
+		 * Read how long it took to see the echo to find the tuning
+		 * row to use.
+		 */
+		linktest = CSR_READ_2(sc, RL_CSCFG) & RL_CSCFG_STATUS;
+		if (linktest == RL_CSCFG_ROW3)
+			sc->rl_twist_row = 3;
+		else if (linktest == RL_CSCFG_ROW2)
+			sc->rl_twist_row = 2;
+		else if (linktest == RL_CSCFG_ROW1)
+			sc->rl_twist_row = 1;
+		else
+			sc->rl_twist_row = 0;
+		sc->rl_twist_col = 0;
+		sc->rl_twister = SET_PARAM;
+		break;
+	case SET_PARAM:
+		if (sc->rl_twist_col == 0)
+			CSR_WRITE_4(sc, RL_NWAYTST, RL_NWAYTST_RESET);
+		CSR_WRITE_4(sc, RL_PARA7C,
+		    param[sc->rl_twist_row][sc->rl_twist_col]);
+		if (++sc->rl_twist_col == 4) {
+			if (sc->rl_twist_row == 3)
+				sc->rl_twister = RECHK_LONG;
+			else
+				sc->rl_twister = DONE;
+		}
+		break;
+	case RECHK_LONG:
+		/*
+		 * For long cables, we have to double check to make sure we
+		 * don't mistune.
+		 */
+		linktest = CSR_READ_2(sc, RL_CSCFG) & RL_CSCFG_STATUS;
+		if (linktest == RL_CSCFG_ROW3)
+			sc->rl_twister = DONE;
+		else {
+			CSR_WRITE_4(sc, RL_PARA7C, RL_PARA7C_RETUNE);
+			sc->rl_twister = RETUNE;
+		}
+		break;
+	case RETUNE:
+		/* Retune for a shorter cable (try column 2) */
+		CSR_WRITE_4(sc, RL_NWAYTST, RL_NWAYTST_CBL_TEST);
+		CSR_WRITE_4(sc, RL_PARA78, RL_PARA78_DEF);
+		CSR_WRITE_4(sc, RL_PARA7C, RL_PARA7C_DEF);
+		CSR_WRITE_4(sc, RL_NWAYTST, RL_NWAYTST_RESET);
+		sc->rl_twist_row--;
+		sc->rl_twist_col = 0;
+		sc->rl_twister = SET_PARAM;
+		break;
+
+	case DONE:
+		break;
+	}
+	
+}
+#endif
+
 static void
 rl_tick(void *xsc)
 {
 	struct rl_softc		*sc = xsc;
 	struct mii_data		*mii;
+	int ticks;
 
 	RL_LOCK_ASSERT(sc);
+	/*
+	 * If we're doing the twister cable calibration, then we need to defer
+	 * watchdog timeouts.  This is a no-op in normal operations, but
+	 * can falsely trigger when the cable calibration takes a while and
+	 * there was traffic ready to go when rl was started.
+	 *
+	 * We don't defer mii_tick since that updates the mii status, which
+	 * helps the twister process, at least according to similar patches
+	 * for the Linux driver I found online while doing the fixes.  Worst
+	 * case is a few extra mii reads during calibration.
+	 */
 	mii = device_get_softc(sc->rl_miibus);
 	mii_tick(mii);
-
+#ifdef RL_TWISTER_ENABLE
+	if (sc->rl_twister == DONE)
+		rl_watchdog(sc);
+	else
+		rl_twister_update(sc);
+	if (sc->rl_twister == DONE)
+		ticks = hz;
+	else
+		ticks = hz / 10;
+#else
 	rl_watchdog(sc);
+	ticks = hz;
+#endif
 
-	callout_reset(&sc->rl_stat_callout, hz, rl_tick, sc);
+	callout_reset(&sc->rl_stat_callout, ticks, rl_tick, sc);
 }
 
 #ifdef DEVICE_POLLING
@@ -1524,7 +1649,7 @@ rl_encap(struct rl_softc *sc, struct mbu
 
 	if (padlen > 0) {
 		/*
-		 * Make security concious people happy: zero out the
+		 * Make security-conscious people happy: zero out the
 		 * bytes in the pad area, since we don't know what
 		 * this mbuf cluster buffer's previous user might
 		 * have left in it.
@@ -1643,6 +1768,14 @@ rl_init_locked(struct rl_softc *sc)
 	rl_stop(sc);
 
 	rl_reset(sc);
+#ifdef RL_TWISTER_ENABLE
+	/*
+	 * Reset twister register tuning state.  The twister registers
+	 * and their tuning are undocumented, but are necessary to cope
+	 * with bad links.  rl_twister = DONE here will disable this entirely.
+	 */
+	sc->rl_twister = CHK_LINK;
+#endif
 
 	/*
 	 * Init our MAC address.  Even though the chipset

Modified: user/imp/newcard/sys/pci/if_rlreg.h
==============================================================================
--- user/imp/newcard/sys/pci/if_rlreg.h	Sat Nov  1 21:16:09 2008	(r184534)
+++ user/imp/newcard/sys/pci/if_rlreg.h	Sat Nov  1 21:49:32 2008	(r184535)
@@ -309,6 +309,27 @@
 #define RL_CMD_RESET		0x0010
 
 /*
+ * Twister register values.  These are completely undocumented and derived
+ * from public sources.

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-user mailing list