Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 4 Jun 2005 05:26:37 GMT
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 77951 for review
Message-ID:  <200506040526.j545Qb4H020145@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=77951

Change 77951 by marcel@marcel_nfs on 2005/06/04 05:26:03

	Submit some large changes before something happens:
	o  Add logic to handle device preemption. If the VGA driver is
	   the low-level console, we need to tell the accelerated driver
	   for the hardware about it. Otherwise it'll initialize the
	   hardware and render the low-level console useless. If the
	   accel driver knows that the hardware is used for the low-
	   level console, it can delay initializing the hardware until
	   the virtual consoles are ready for use.
	o  Have the GMCH driver save the device_t of the DRAM controller
	   so that it can figure out the refresh rate of the local
	   memory. This is needed to properly program the hardware.
	o  If the VGA driver attaches during bus enumeration, register
	   it with VTC. This will trigger the creation of a virtual
	   terminal with terminal emulator.
	o  Prevent the VGA driver from probing the ISA bus when we have
	   found PCI based hardware.
	o  Express the display depth in bits, not colors.
	o  Implement the bulk of the VTC TTY layer. Needs a more work.
	o  Implement TE support functions. A single TE can drive more
	   than one graphics card and they don't have to have the same
	   resolution. To deal with this, TEs operate with a character-
	   based resolution (80x24 for VT100). Based on this and the
	   resolution of the graphics device, a matching font is found
	   by the TE support layer. To support double-width and double-
	   height modes, a scaling factor is passed down to the support
	   functions so that a bigger font can be selected.
	
	Note: The initial configuration of VTC maps all graphics cards
	and keyboards (not yet dealt with) to a single virtual terminal.
	Once in multi-user mode, this should be reconfigurable so that
	there's a TE per graphics card.

Affected files ...

.. //depot/projects/tty/sys/dev/vtc/hw/gmch/gmch.c#3 edit
.. //depot/projects/tty/sys/dev/vtc/hw/gmch/gmch_bus_pci.c#4 edit
.. //depot/projects/tty/sys/dev/vtc/hw/vga/vga.c#3 edit
.. //depot/projects/tty/sys/dev/vtc/hw/vga/vga.h#3 edit
.. //depot/projects/tty/sys/dev/vtc/hw/vga/vga_bus_isa.c#3 edit
.. //depot/projects/tty/sys/dev/vtc/hw/vga/vga_bus_pci.c#3 edit
.. //depot/projects/tty/sys/dev/vtc/hw/vga/vga_con.c#3 edit
.. //depot/projects/tty/sys/dev/vtc/vtc_con.c#9 edit
.. //depot/projects/tty/sys/dev/vtc/vtc_con.h#3 edit
.. //depot/projects/tty/sys/dev/vtc/vtc_core.c#5 edit
.. //depot/projects/tty/sys/dev/vtc/vtc_font.c#5 edit
.. //depot/projects/tty/sys/dev/vtc/vtc_logo.c#3 edit
.. //depot/projects/tty/sys/dev/vtc/vtc_te.c#2 edit
.. //depot/projects/tty/sys/dev/vtc/vtc_te.h#3 edit
.. //depot/projects/tty/sys/dev/vtc/vtc_te_if.m#3 edit
.. //depot/projects/tty/sys/dev/vtc/vtc_te_vt102.c#3 edit
.. //depot/projects/tty/sys/dev/vtc/vtc_tty.c#2 edit

Differences ...

==== //depot/projects/tty/sys/dev/vtc/hw/gmch/gmch.c#3 (text+ko) ====

@@ -34,6 +34,7 @@
 #include <sys/bus.h>
 #include <sys/rman.h>
 
+#include <dev/vtc/vtc_vtout.h>
 #include <dev/vtc/hw/gmch/gmch.h>
 
 devclass_t gmch_devclass;
@@ -44,6 +45,9 @@
 {
 	struct gmch_softc *sc;
 
+	if (vtc_vtout_console(dev))
+		device_printf(dev, "console!\n");
+
 	sc = device_get_softc(dev);
 	sc->gmch_dev = dev;
 	return (0);

==== //depot/projects/tty/sys/dev/vtc/hw/gmch/gmch_bus_pci.c#4 (text+ko) ====

@@ -42,9 +42,12 @@
 #include <dev/vtc/hw/gmch/gmch.h>
 
 #define	PCI_VENDOR_INTEL	0x8086
-#define	PCI_DEVICE_I815		0x1132
+#define	PCI_DEVICE_I815_DRAM	0x1130
+#define	PCI_DEVICE_I815_GUI	0x1132
 #define	PCI_DEVICE_I830M	0x3577
 
+static device_t gmch_dram_controller;
+
 static int gmch_pci_attach(device_t dev);
 static int gmch_pci_probe(device_t dev);
 
@@ -91,13 +94,23 @@
 gmch_pci_probe(device_t dev)
 {
 
+	if (pci_get_vendor(dev) != PCI_VENDOR_INTEL)
+		return (ENXIO);
+
+	/*
+	 * Save the device_t of the DRAM controller of the i815 chipset.
+	 * We need it in case we do get to attach to the GUI accel.
+	 */
+	if (pci_get_device(dev) == PCI_DEVICE_I815_DRAM) {
+		gmch_dram_controller = dev;
+		return (ENXIO);
+	}
+
 	if (pci_get_class(dev) != PCIC_DISPLAY)
 		return (ENXIO);
-	if (pci_get_vendor(dev) != PCI_VENDOR_INTEL)
-		return (ENXIO);
 
 	switch (pci_get_device(dev)) {
-	case PCI_DEVICE_I815:
+	case PCI_DEVICE_I815_GUI:
 		device_set_desc(dev, "82815/EM/EP/P Internal GUI Accelerator");
 		break;
 	case PCI_DEVICE_I830M:

==== //depot/projects/tty/sys/dev/vtc/hw/vga/vga.c#3 (text+ko) ====

@@ -34,9 +34,11 @@
 #include <sys/bus.h>
 #include <sys/rman.h>
 
+#include <dev/vtc/vtc.h>
+#include <dev/vtc/vtc_vtout.h>
+
 #include <dev/ic/vga.h>
 #include <dev/vtc/hw/vga/vga.h>
-#include <dev/vtc/vtc.h>
 
 /* Convenience macros. */
 #define	MEM_READ(sc, ofs)		\
@@ -441,6 +443,20 @@
 	return (error);
 }
 
+static int
+vga_bitblt(void *cookie, int op, uintptr_t src, uintptr_t dst, int width,
+    int height, ...)
+{
+	struct vga_softc *sc = (struct vga_softc *)cookie;
+	va_list ap;
+	int error;
+
+	va_start(ap, height);
+	error = vga_vbitblt(sc, op, src, dst, width, height, ap);
+	va_end(ap);
+	return (error);
+}
+
 int
 vga_attach(device_t dev)
 {
@@ -460,5 +476,5 @@
 	    640 * (480 - vtc_logo4_height) / 2 + (640 - vtc_logo4_width) / 2,
 	    vtc_logo4_width, vtc_logo4_height);
 
-	return (0);
+	return (vtc_vtout_attach(sc, vga_bitblt, 640, 480));
 }

==== //depot/projects/tty/sys/dev/vtc/hw/vga/vga.h#3 (text+ko) ====

@@ -41,6 +41,7 @@
 {
 	device_t	vga_dev;
 	dev_t		vga_node;
+	struct vtc_conout *vga_conout;
 
 	/* Device flags and state. */
 	int		vga_bustype:2;

==== //depot/projects/tty/sys/dev/vtc/hw/vga/vga_bus_isa.c#3 (text+ko) ====

@@ -39,6 +39,8 @@
 #include <isa/isareg.h>
 #include <isa/isavar.h>
 
+#include <dev/vtc/vtc_con.h>
+
 #include <dev/ic/vga.h>
 #include <dev/vtc/hw/vga/vga.h>
 
@@ -69,6 +71,14 @@
 vga_isa_probe(device_t dev)
 {
 
+	/*
+	 * We can get called even when there's a PCI VGA device. It happens
+	 * when an accelerated driver for the hardware exists that preempts
+	 * the VGA driver. We check for this and bail out right away.
+	 */
+	if (vga_console.vga_conout->vtc_busdev != NULL)
+		return (ENXIO);
+
 	printf("ISA VGA is being probed!\n");
 	return (ENXIO);
 }

==== //depot/projects/tty/sys/dev/vtc/hw/vga/vga_bus_pci.c#3 (text+ko) ====

@@ -39,6 +39,8 @@
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
 
+#include <dev/vtc/vtc_con.h>
+
 #include <dev/ic/vga.h>
 #include <dev/vtc/hw/vga/vga.h>
 
@@ -132,6 +134,20 @@
 	if ((cfg & PCIM_CMD_PORTEN) == 0)
 		return (ENXIO);
 
+	/*
+	 * Handle preemption in case we're the VTC console. We typically
+	 * don't get to attach when there's an accelerated driver for the
+	 * hardware. The problem is that we like to continue to use the
+	 * hardware for the low-level console until we're ready to switch
+	 * to the virtual terminal, at which time the accelerated driver
+	 * can take control. We handshake by letting VTC know what the
+	 * device_t for the hardware is so that accelerated drivers can
+	 * check whether they're attaching to the low-level console device
+	 * or not and take appropriate action.
+	 */
+	if (vga_console.vga_console)
+		vga_console.vga_conout->vtc_busdev = dev;
+
 	return (BUS_PROBE_GENERIC);
 }
 

==== //depot/projects/tty/sys/dev/vtc/hw/vga/vga_con.c#3 (text+ko) ====

@@ -65,7 +65,7 @@
 	co->vtc_con_cookie = &vga_console;
 	co->vtc_con_width = 640;
 	co->vtc_con_height = 480;
-	co->vtc_con_depth = 16;
+	co->vtc_con_depth = 4;
 	return (0);
 }
 
@@ -74,8 +74,10 @@
 {
 	struct vga_softc *sc = co->vtc_con_cookie;
 
-	if (vga_init(sc) == 0)
+	if (vga_init(sc) == 0) {
+		sc->vga_conout = co;
 		sc->vga_console = 1;
+	}
 }
 
 static void

==== //depot/projects/tty/sys/dev/vtc/vtc_con.c#9 (text+ko) ====

@@ -52,8 +52,6 @@
 CONS_DRIVER(vtc, vtc_cnprobe, vtc_cninit, vtc_cnterm, vtc_cngetc, vtc_cncheckc,
     vtc_cnputc, NULL);
 
-SET_DECLARE(vtc_conout_set, struct vtc_conout);
-
 static void
 vtc_cnprobe(struct consdev *cp)
 {
@@ -80,6 +78,7 @@
 {
 	struct vtc_conout *vc = cp->cn_arg;
 
+	vc->vtc_consdev = cp;
 	vc->vtc_con_init(vc);
 }
 

==== //depot/projects/tty/sys/dev/vtc/vtc_con.h#3 (text+ko) ====

@@ -37,11 +37,13 @@
 typedef int  vtc_con_probe_f(struct vtc_conout *);
 
 struct vtc_conout {
+	struct consdev	*vtc_consdev;
+	device_t	vtc_busdev;
 	const char	*vtc_con_name;
 	vtc_con_probe_f	*vtc_con_probe;
 	vtc_con_init_f	*vtc_con_init;
 	vtc_con_bitblt_f *vtc_con_bitblt;
-	void *		vtc_con_cookie;
+	void		*vtc_con_cookie;
 	int		vtc_con_width;
 	int		vtc_con_height;
 	int		vtc_con_depth;
@@ -53,11 +55,9 @@
 		.vtc_con_probe = probe,				\
 		.vtc_con_init = init,				\
 		.vtc_con_bitblt = bitblt,			\
-		.vtc_con_cookie = NULL,				\
-		.vtc_con_width = -1,				\
-		.vtc_con_height = -1,				\
-		.vtc_con_depth = -1				\
 	};							\
 	DATA_SET(vtc_conout_set, name##_vtc_conout)
 
+SET_DECLARE(vtc_conout_set, struct vtc_conout);
+
 #endif /* !_DEV_VTC_CON_H_ */

==== //depot/projects/tty/sys/dev/vtc/vtc_core.c#5 (text+ko) ====

@@ -1,4 +1,4 @@
-/*
+/*-
  * Copyright (c) 2003-2005 Marcel Moolenaar
  * All rights reserved.
  *
@@ -29,14 +29,161 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/bus.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
+#include <sys/kobj.h>
+#include <sys/malloc.h>
 #include <sys/module.h>
+#include <sys/tty.h>
 
 #include <dev/vtc/vtc.h>
+#include <dev/vtc/vtc_con.h>
+#include <dev/vtc/vtc_te.h>
+#include <dev/vtc/vtc_vtout.h>
 
+#include "vtc_te_if.h"
+
 char vtc_device_name[] = "vtc";
 
+TAILQ_HEAD(, vtc_te_softc) vtc_te_devs =
+    TAILQ_HEAD_INITIALIZER(vtc_te_devs);
+TAILQ_HEAD(, vtc_vtout_softc) vtc_vtout_devs =
+    TAILQ_HEAD_INITIALIZER(vtc_vtout_devs);
+
+MALLOC_DEFINE(M_VTC, "VTC", "VTC driver");
+
+extern struct vtc_te_class vt102_class;
+
+static int
+vtc_tty_open(struct tty *tp, struct cdev *dev)
+{
+	struct vtc_te_softc *te;
+
+	te = tp->t_sc;
+	/* XXX notify the TE that we're opened? */
+	return (0);
+}
+
+static void
+vtc_tty_close(struct tty *tp)
+{
+	struct vtc_te_softc *te;
+
+	te = tp->t_sc;
+	if (te == NULL)
+		return;
+
+	wakeup(te);
+}
+
+static void
+vtc_tty_oproc(struct tty *tp)
+{
+	struct vtc_te_softc *te;
+
+	te = tp->t_sc;
+	if (te == NULL)
+		return;
+
+	if (tp->t_state & (TS_TTSTOP | TS_BUSY))
+		return;
+
+	if (tp->t_outq.c_cc > 0) {
+		tp->t_state |= TS_BUSY;
+		/* XXX loop to display all characters in the buffer. */
+		tp->t_state &= ~TS_BUSY;
+	}
+
+	ttwwakeup(tp);
+}
+
+static int
+vtc_tty_param(struct tty *tp, struct termios *t)
+{
+	struct vtc_te_softc *te;
+
+	te = tp->t_sc;
+	if (te == NULL)
+		return (ENODEV);
+
+	ttsetwater(tp);
+	return (0);
+}
+
+static int
+vtc_tty_modem(struct tty *tp, int biton, int bitoff)
+{
+
+	return (0);
+}
+
+static void
+vtc_tty_break(struct tty *tp, int state)
+{
+}
+
+static void
+vtc_tty_stop(struct tty *tp, int rw)
+{
+}
+
+int
+vtc_vtout_attach(void *cookie, vtout_bitblt_f bitblt, int width, int height)
+{
+	struct vtc_te_softc *te;
+	struct tty *tp;
+	struct vtc_vtout_softc *vo;
+
+	vo = malloc(sizeof(*vo), M_VTC, M_WAITOK|M_ZERO);
+	TAILQ_INSERT_TAIL(&vtc_vtout_devs, vo, vo_alldevs);
+	vo->vo_cookie = cookie;
+	vo->vo_bitblt = bitblt;
+	vo->vo_width = width;
+	vo->vo_height = height;
+
+	te = malloc(vt102_class.size, M_VTC, M_WAITOK|M_ZERO);
+	TAILQ_INSERT_TAIL(&vtc_te_devs, te, te_alldevs);
+	TAILQ_INIT(&te->te_vodevs);
+	TAILQ_INSERT_TAIL(&te->te_vodevs, vo, vo_tedevs);
+
+	VTC_TE_RESET(te);
+
+	tp = ttyalloc();
+	te->te_tty = tp;
+	tp->t_sc = te;
+
+	tp->t_oproc = vtc_tty_oproc;
+	tp->t_param = vtc_tty_param;
+	tp->t_stop = vtc_tty_stop;
+	tp->t_modem = vtc_tty_modem;
+	tp->t_break = vtc_tty_break;
+	tp->t_open = vtc_tty_open;
+	tp->t_close = vtc_tty_close;
+
+/*
+	sprintf(((struct consdev *)sc->sc_sysdev->cookie)->cn_name, "ttyv%r",
+	    unit);
+*/
+	ttyconsolemode(tp, 0);
+
+	ttycreate(tp, NULL, 0, MINOR_CALLOUT, "v%r", 0);
+	return (0);
+}
+
+int
+vtc_vtout_console(device_t dev)
+{
+	struct vtc_conout *vc, **iter;
+
+	SET_FOREACH(iter, vtc_conout_set) {
+		vc = *iter;
+		if (vc->vtc_busdev == dev)
+			return (1);
+	}
+	return (0);
+}
+
 static int
 vtc_modevent(module_t mod, int type, void *data)
 {

==== //depot/projects/tty/sys/dev/vtc/vtc_font.c#5 (text+ko) ====

@@ -27,6 +27,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/param.h>
+
 #include <dev/vtc/vtc.h>
 
 unsigned char vtc_font_8x16[95 * 16] = {

==== //depot/projects/tty/sys/dev/vtc/vtc_logo.c#3 (text+ko) ====

@@ -27,6 +27,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/param.h>
+
 #include <dev/vtc/vtc.h>
 
 #define	__	0

==== //depot/projects/tty/sys/dev/vtc/vtc_te.c#2 (text+ko) ====

@@ -31,11 +31,70 @@
 #include <sys/systm.h>
 #include <sys/kobj.h>
 
+#include <dev/vtc/vtc.h>
 #include <dev/vtc/vtc_te.h>
+#include <dev/vtc/vtc_vtout.h>
+
+int
+vtc_te_bell(struct vtc_te_softc *te)
+{
+
+	return (ENXIO);
+}
 
 int
-vtc_te_bell(struct vtc_te_softc *sc)
+vtc_te_putc(struct vtc_te_softc *te, int row, int col, int ws, int hs, int fl,
+    __wchar_t wc)
+{
+	struct vtc_vtout_softc *vo;
+	uint8_t *glyph;
+
+	KASSERT(wc >= 0x20, ("Unexpected control character"));
+
+	TAILQ_FOREACH(vo, &te->te_vodevs, vo_tedevs) {
+		if (vo->vo_ws != ws || vo->vo_hs != hs) {
+			vo->vo_cw = (vo->vo_width / te->te_maxcol) * ws;
+			vo->vo_ch = (vo->vo_height / te->te_maxrow) * hs;
+			/*
+			 * Lookup matching font, with glyphs no wider than
+			 * vtout->vo_cw and no higher than vtout->vo_ch.
+			 */
+			vo->vo_font = vtc_font_8x16;
+		}
+
+		glyph = vo->vo_font + (wc - 0x20) * 16;
+		vo->vo_bitblt(vo->vo_cookie, BITBLT_H1TOFB, (uintptr_t)glyph,
+		    vo->vo_width * row * vo->vo_ch + col * vo->vo_cw,
+		    8, 16, 0, 7);
+	}
+	return (0);
+}
+
+int
+vtc_te_repos(struct vtc_te_softc *te, int row, int col)
 {
 
 	return (ENXIO);
 }
+
+int
+vtc_te_scroll(struct vtc_te_softc *te, int ulr, int ulc, int lrr, int lrc,
+    int hs)
+{
+	struct vtc_vtout_softc *vo;
+	int ch, cw;
+
+	TAILQ_FOREACH(vo, &te->te_vodevs, vo_tedevs) {
+		ch = vo->vo_height / te->te_maxrow;
+		cw = vo->vo_width / te->te_maxcol;
+
+		vo->vo_bitblt(vo->vo_cookie, BITBLT_FBTOFB,
+		    vo->vo_width * (ulr + hs) * ch + ulc * cw,
+		    vo->vo_width * ulr * ch + ulc * cw,
+		    (lrc - ulc) * cw, (lrr - ulr - hs) * ch);
+
+		vo->vo_bitblt(vo->vo_cookie, BITBLT_CTOFB, 0,
+		    (lrr - hs) * ch, (lrc - ulc) * cw, hs * ch);
+	}
+	return (0);
+}

==== //depot/projects/tty/sys/dev/vtc/vtc_te.h#3 (text+ko) ====

@@ -38,12 +38,20 @@
 
 struct vtc_te_softc {
 	KOBJ_FIELDS;
-	struct vtc_te_class *sc_class;
+	struct vtc_te_class *te_class;
+	TAILQ_ENTRY(vtc_te_softc) te_alldevs;
+	TAILQ_HEAD(, vtc_vtout_softc) te_vodevs;
+	struct tty *te_tty;
+	int	te_maxcol;
+	int	te_maxrow;
 };
 
 /*
  * TE support functions.
  */
 int vtc_te_bell(struct vtc_te_softc *);
+int vtc_te_putc(struct vtc_te_softc *, int, int, int, int, int, __wchar_t);
+int vtc_te_repos(struct vtc_te_softc *, int, int);
+int vtc_te_scroll(struct vtc_te_softc *, int, int, int, int, int);
 
 #endif /* !_DEV_VTC_TE_H_ */

==== //depot/projects/tty/sys/dev/vtc/vtc_te_if.m#3 (text+ko) ====

@@ -35,6 +35,11 @@
 
 INTERFACE vtc_te;
 
+# reset() - initialize/reset
+METHOD int reset {
+	struct vtc_te_softc *this;
+};
+
 # write() - write to the terminal
 METHOD int write {
 	struct vtc_te_softc *this;

==== //depot/projects/tty/sys/dev/vtc/vtc_te_vt102.c#3 (text+ko) ====

@@ -45,11 +45,22 @@
 	int	state;
 	int	count;
 	char	cbuf[16];
+	int	col, row;
+	int	maxcol, maxrow;
+
+	int	autowrap:1;
+	int	dh:1;
+	int	dw:1;
+	int	underline:1;
+
+	int	wrap:1;
 };
 
+static int vt102_reset(struct vtc_te_softc *);
 static int vt102_write(struct vtc_te_softc *, __wchar_t);
 
 static kobj_method_t vt102_methods[] = {
+	KOBJMETHOD(vtc_te_reset,	vt102_reset),
 	KOBJMETHOD(vtc_te_write,	vt102_write),
 	{ 0, 0 }
 };
@@ -60,15 +71,58 @@
 	sizeof(struct vt102_softc),
 };
 
+static __inline int
+vt102_putc(struct vt102_softc *vt102, __wchar_t wc)
+{
+
+	return (vtc_te_putc(&vt102->base, vt102->row << vt102->dh,
+		vt102->col << vt102->dw, 1 << vt102->dw, 1 << vt102->dh,
+		vt102->underline, wc));
+}
+
+static __inline int
+vt102_repos(struct vt102_softc *vt102)
+{
+
+	vt102->wrap = 0;
+	return (vtc_te_repos(&vt102->base, vt102->row << vt102->dh,
+		vt102->col << vt102->dw));
+}
+
+static __inline int
+vt102_newline(struct vt102_softc *vt102)
+{
+
+	if (vt102->row == vt102->maxrow)
+		return (vtc_te_scroll(&vt102->base, 0, 0,
+			vt102->maxrow << vt102->dh, vt102->maxcol << vt102->dw,
+			1 << vt102->dh));
+	vt102->row++;
+	return (vt102_repos(vt102));
+}
+
 static int
 vt102_answerback(struct vt102_softc *vt102)
 {
 	return (0);
 }
 
-static int
+static __inline int
 vt102_print(struct vt102_softc *vt102, __wchar_t wc)
 {
+
+	if (vt102->autowrap && vt102->wrap) {
+		vt102->col = 0;
+		vt102_newline(vt102);
+	}
+	vt102_putc(vt102, wc);
+	vt102->col++;
+	if (vt102->col > vt102->maxcol) {
+		vt102->col = vt102->maxcol;
+		if (vt102->autowrap)
+			vt102->wrap = 1;
+	} else
+		vt102_repos(vt102);
 	return (0);
 }
 
@@ -85,18 +139,42 @@
 		error = vtc_te_bell(&vt102->base);
 		break;
 	case 0x08:	/* BS */
+		if (vt102->col > 0) {
+			vt102->col--;
+			vt102_putc(vt102, ' ');
+			vt102_repos(vt102);
+		}
 		break;
 	case 0x09:	/* HT */
+		if (vt102->col < vt102->maxcol) {
+			vt102->col = (vt102->col + 8) & ~7;
+			if (vt102->col > vt102->maxcol)
+				vt102->col = vt102->maxcol;
+			vt102_repos(vt102);
+		}
 		break;
 	case 0x0A:	/* LF */
 	case 0x0B:	/* VT (processed as LF) */
 	case 0x0C:	/* FF (processed as LF) */
+		vt102_newline(vt102);
 		break;
 	case 0x0D:	/* CR */
+		if (vt102->col > 0) {
+			vt102->col = 0;
+			vt102_repos(vt102);
+		}
 		break;
 	case 0x0E:	/* SO */
+		/*
+		 * Select G1 character set. We're Unicode, hence no character
+		 * set switching.
+		 */
 		break;
 	case 0x0F:	/* SI */
+		/*
+		 * Select G0 character set. We're Unicode, hence no character
+		 * set switching.
+		 */
 		break;
 	case 0x18:	/* CAN */
 	case 0x1A:	/* SUB (processed as CAN) */
@@ -127,9 +205,24 @@
 }
 
 static int
-vt102_write(struct vtc_te_softc *sc, __wchar_t wc)
+vt102_reset(struct vtc_te_softc *te)
+{
+	struct vt102_softc *vt102 = (struct vt102_softc *)te;
+
+	te->te_maxcol = 80;
+	te->te_maxrow = 24;
+
+	vt102->maxcol = 80;
+	vt102->maxrow = 24;
+
+	vt102->autowrap = 1;
+	return (0);
+}
+
+static int
+vt102_write(struct vtc_te_softc *te, __wchar_t wc)
 {
-	struct vt102_softc *vt102 = (struct vt102_softc *)sc;
+	struct vt102_softc *vt102 = (struct vt102_softc *)te;
 	int error;
 
 	KASSERT(wc >= 0, ("Negative UTF-32 characters don't exist!"));

==== //depot/projects/tty/sys/dev/vtc/vtc_tty.c#2 (text+ko) ====

@@ -27,6 +27,122 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-vtc_tty_write(struct vtc_tty_softc *sc, wchar_t wc)
+#include <dev/vtc/vtc_te.h>
+
+static int
+vtc_tty_open(struct tty *tp, struct cdev *dev)
+{
+	struct vtc_te_softc *sc;
+
+	sc = tp->t_sc;
+	/* XXX notify the TE that we're opened? */
+	return (0);
+}
+
+static void
+vtc_tty_close(struct tty *tp)
+{
+	struct vtc_te_softc *sc;
+
+	sc = tp->t_sc;
+	if (sc == NULL)
+		return;
+
+	wakeup(sc);
+	return;
+}
+
+static void
+vtc_tty_oproc(struct tty *tp)
+{
+	struct vtc_te_softc *sc;
+
+	sc = tp->t_sc;
+	if (sc == NULL)
+		return;
+
+	if (tp->t_state & (TS_TTSTOP | TS_BUSY))
+		return;
+
+	if (tp->t_outq.c_cc > 0) {
+		tp->t_state |= TS_BUSY;
+		/* XXX loop to display all characters in the buffer. */
+		tp->t_state &= ~TS_BUSY;
+	}
+
+	ttwwakeup(tp);
+}
+
+static int
+vtc_tty_param(struct tty *tp, struct termios *t)
+{
+	struct vtc_te_softc *sc;
+
+	sc = tp->t_sc;
+	if (sc == NULL)
+		return (ENODEV);
+
+	ttsetwater(tp);
+	return (0);
+}
+
+static int
+vtc_tty_modem(struct tty *tp, int biton, int bitoff)
+{
+
+	return (0);
+}
+
+static void
+vtc_tty_break(struct tty *tp, int state)
+{
+}
+
+static void
+vtc_tty_stop(struct tty *tp, int rw)
+{
+}
+
+int
+vtc_tty_attach(struct vtc_te_softc *sc)
+{
+	struct tty *tp;
+	int unit;
+
+	tp = ttyalloc();
+	sc->sc_u.u_tty.tp = tp;
+	tp->t_sc = sc;
+
+	unit = device_get_unit(sc->sc_dev);
+
+	tp->t_oproc = uart_tty_oproc;
+	tp->t_param = uart_tty_param;
+	tp->t_stop = uart_tty_stop;
+	tp->t_modem = uart_tty_modem;
+	tp->t_break = uart_tty_break;
+	tp->t_open = uart_tty_open;
+	tp->t_close = uart_tty_close;
+
+	tp->t_pps = &sc->sc_pps;
+
+	if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
+		sprintf(((struct consdev *)sc->sc_sysdev->cookie)->cn_name,
+		    "ttyu%r", unit);
+		ttyconsolemode(tp, 0);
+	}
+
+	ttycreate(tp, NULL, 0, MINOR_CALLOUT, "v%r", unit);
+
+	return (0);
+}
+
+int vtc_tty_detach(struct vtc_te_softc *sc)
 {
+	struct tty *tp;
+
+	tp = sc->sc_u.u_tty.tp;
+	ttygone(tp);
+	ttyfree(tp);
+
+	return (0);
 }



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