xref: /illumos-gate/usr/src/uts/common/io/wscons.c (revision 7edfb5b0)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5fea9cb91Slq  * Common Development and Distribution License (the "License").
6fea9cb91Slq  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21fea9cb91Slq 
227c478bd9Sstevel@tonic-gate /*
23ceeba6f9Srui zang - Sun Microsystems - Beijing China  * Copyright (c) 1987, 2010, Oracle and/or its affiliates. All rights reserved.
24d4a54bf7SToomas Soome  * Copyright 2019 Toomas Soome <tsoome@me.com>
2536d47380SJohn Levon  * Copyright 2019 Joyent, Inc.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * "Workstation console" multiplexor driver for Sun.
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * Sends output to the primary frame buffer using the PROM monitor;
327c478bd9Sstevel@tonic-gate  * gets input from a stream linked below us that is the "keyboard
337c478bd9Sstevel@tonic-gate  * driver", below which is linked the primary keyboard.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
36aecfc01dSrui zang - Sun Microsystems - Beijing China /*
37aecfc01dSrui zang - Sun Microsystems - Beijing China  * Locking Policy:
38aecfc01dSrui zang - Sun Microsystems - Beijing China  * This module has a D_MTPERMOD inner perimeter which means STREAMS
39aecfc01dSrui zang - Sun Microsystems - Beijing China  * only allows one thread to enter this module through STREAMS entry
40aecfc01dSrui zang - Sun Microsystems - Beijing China  * points each time -- open() close() put() srv() qtimeout().
41aecfc01dSrui zang - Sun Microsystems - Beijing China  * So for the most time we do not need locking in this module, but with
42aecfc01dSrui zang - Sun Microsystems - Beijing China  * the following exceptions:
43aecfc01dSrui zang - Sun Microsystems - Beijing China  *
44ceeba6f9Srui zang - Sun Microsystems - Beijing China  *   - wc shares three global variables (wc_dip, vc_active_console,
45ceeba6f9Srui zang - Sun Microsystems - Beijing China  *     vc_cons_user, vc_avl_root) with virtual console devname part
46ceeba6f9Srui zang - Sun Microsystems - Beijing China  *    (fs/dev/sdev_vtops.c) which get compiled into genunix.
47aecfc01dSrui zang - Sun Microsystems - Beijing China  *
48aecfc01dSrui zang - Sun Microsystems - Beijing China  *   - wc_modechg_cb() is a callback function which will triggered when
49aecfc01dSrui zang - Sun Microsystems - Beijing China  *     framebuffer display mode is changed.
50aecfc01dSrui zang - Sun Microsystems - Beijing China  *
51aecfc01dSrui zang - Sun Microsystems - Beijing China  *   - vt_send_hotkeys() is triggered by timeout() which is not STREAMS MT
52aecfc01dSrui zang - Sun Microsystems - Beijing China  *     safe.
53aecfc01dSrui zang - Sun Microsystems - Beijing China  *
54aecfc01dSrui zang - Sun Microsystems - Beijing China  * Based on the fact that virtual console devname part and wc_modechg_cb()
55ceeba6f9Srui zang - Sun Microsystems - Beijing China  * only do read access to the above mentioned shared four global variables,
56aecfc01dSrui zang - Sun Microsystems - Beijing China  * It is safe to do locking this way:
57ceeba6f9Srui zang - Sun Microsystems - Beijing China  * 1) all read access to the four global variables in THIS WC MODULE do not
58aecfc01dSrui zang - Sun Microsystems - Beijing China  *    need locking;
59ceeba6f9Srui zang - Sun Microsystems - Beijing China  * 2) all write access to the four global variables in THIS WC MODULE must
60aecfc01dSrui zang - Sun Microsystems - Beijing China  *    hold vc_lock;
61ceeba6f9Srui zang - Sun Microsystems - Beijing China  * 3) any access to the four global variables in either DEVNAME PART or the
62aecfc01dSrui zang - Sun Microsystems - Beijing China  *    CALLBACK must hold vc_lock;
63aecfc01dSrui zang - Sun Microsystems - Beijing China  * 4) other global variables which are only shared in this wc module and only
64aecfc01dSrui zang - Sun Microsystems - Beijing China  *    accessible through STREAMS entry points such as "vc_last_console",
65aecfc01dSrui zang - Sun Microsystems - Beijing China  *    "vc_inuse_max_minor", "vc_target_console" and "vc_waitactive_list"
66aecfc01dSrui zang - Sun Microsystems - Beijing China  *    do not need explict locking.
67aecfc01dSrui zang - Sun Microsystems - Beijing China  *
68aecfc01dSrui zang - Sun Microsystems - Beijing China  * wc_modechg_cb() does read access to vc_state_t::vc_flags,
69aecfc01dSrui zang - Sun Microsystems - Beijing China  * vc_state_t::vc_state_lock is used to protect concurrently accesses to
70aecfc01dSrui zang - Sun Microsystems - Beijing China  * vc_state_t::vc_flags which may happen from both through STREAMS entry
71aecfc01dSrui zang - Sun Microsystems - Beijing China  * points and wc_modechg_cb().
72aecfc01dSrui zang - Sun Microsystems - Beijing China  * Since wc_modechg_cb() only does read access to vc_state_t::vc_flags,
73aecfc01dSrui zang - Sun Microsystems - Beijing China  * The other parts of wc module (except wc_modechg_cb()) only has to hold
74aecfc01dSrui zang - Sun Microsystems - Beijing China  * vc_state_t::vc_flags when writing to vc_state_t::vc_flags.
75aecfc01dSrui zang - Sun Microsystems - Beijing China  *
76aecfc01dSrui zang - Sun Microsystems - Beijing China  * vt_send_hotkeys() could access vt_pending_vtno at the same time with
77aecfc01dSrui zang - Sun Microsystems - Beijing China  * the rest of wc module, vt_pending_vtno_lock is used to protect
78aecfc01dSrui zang - Sun Microsystems - Beijing China  * vt_pending_vtno.
79aecfc01dSrui zang - Sun Microsystems - Beijing China  *
80aecfc01dSrui zang - Sun Microsystems - Beijing China  * Lock order: vc_lock -> vc_state_t::vc_state_lock.
81aecfc01dSrui zang - Sun Microsystems - Beijing China  * No overlap between vc_lock and vt_pending_vtno_lock.
82aecfc01dSrui zang - Sun Microsystems - Beijing China  */
83aecfc01dSrui zang - Sun Microsystems - Beijing China 
847c478bd9Sstevel@tonic-gate #include <sys/types.h>
857c478bd9Sstevel@tonic-gate #include <sys/param.h>
867c478bd9Sstevel@tonic-gate #include <sys/signal.h>
877c478bd9Sstevel@tonic-gate #include <sys/cred.h>
887c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
897c478bd9Sstevel@tonic-gate #include <sys/termios.h>
907c478bd9Sstevel@tonic-gate #include <sys/termio.h>
917c478bd9Sstevel@tonic-gate #include <sys/ttold.h>
927c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
937c478bd9Sstevel@tonic-gate #include <sys/stream.h>
947c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
957c478bd9Sstevel@tonic-gate #include <sys/tty.h>
967c478bd9Sstevel@tonic-gate #include <sys/buf.h>
977c478bd9Sstevel@tonic-gate #include <sys/uio.h>
987c478bd9Sstevel@tonic-gate #include <sys/stat.h>
99aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/sysmacros.h>
100aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/errno.h>
101aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/proc.h>
102aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/procset.h>
103aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/fault.h>
104aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/siginfo.h>
105aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/debug.h>
106aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/session.h>
1077c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
1087c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
1097c478bd9Sstevel@tonic-gate #include <sys/kbio.h>
1107c478bd9Sstevel@tonic-gate #include <sys/strredir.h>
1117c478bd9Sstevel@tonic-gate #include <sys/fs/snode.h>
1127c478bd9Sstevel@tonic-gate #include <sys/consdev.h>
1137c478bd9Sstevel@tonic-gate #include <sys/conf.h>
114aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/cmn_err.h>
115aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/console.h>
116aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/promif.h>
117aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/note.h>
118aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/polled_io.h>
119aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/systm.h>
1207c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
1217c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
122aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/sunndi.h>
123aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/esunddi.h>
124aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/sunldi.h>
1257c478bd9Sstevel@tonic-gate #include <sys/debug.h>
1267c478bd9Sstevel@tonic-gate #include <sys/console.h>
1277c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
1287c478bd9Sstevel@tonic-gate #include <sys/policy.h>
129aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/modctl.h>
130fea9cb91Slq #include <sys/tem.h>
131fea9cb91Slq #include <sys/wscons.h>
132aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/vt_impl.h>
133aecfc01dSrui zang - Sun Microsystems - Beijing China 
134aecfc01dSrui zang - Sun Microsystems - Beijing China /* streams stuff */
135aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("Unshared data", copyreq))
136aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("Unshared data", copyresp))
137aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("Unshared data", datab))
138aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("Unshared data", iocblk))
139aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("Unshared data", msgb))
140aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("Unshared data", queue))
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate #define	MINLINES	10
1437c478bd9Sstevel@tonic-gate #define	MAXLINES	48
1447c478bd9Sstevel@tonic-gate #define	LOSCREENLINES	34
1457c478bd9Sstevel@tonic-gate #define	HISCREENLINES	48
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate #define	MINCOLS		10
1487c478bd9Sstevel@tonic-gate #define	MAXCOLS		120
1497c478bd9Sstevel@tonic-gate #define	LOSCREENCOLS	80
1507c478bd9Sstevel@tonic-gate #define	HISCREENCOLS	120
1517c478bd9Sstevel@tonic-gate 
152aecfc01dSrui zang - Sun Microsystems - Beijing China struct wscons_state {
1537c478bd9Sstevel@tonic-gate 	dev_t	wc_dev;			/* major/minor for this device */
154fea9cb91Slq #ifdef _HAVE_TEM_FIRMWARE
1557c478bd9Sstevel@tonic-gate 	int	wc_defer_output;	/* set if output device is "slow" */
156fea9cb91Slq #endif /* _HAVE_TEM_FIRMWARE */
1577c478bd9Sstevel@tonic-gate 	queue_t	*wc_kbdqueue;		/* "console keyboard" device queue */
1587c478bd9Sstevel@tonic-gate 					/* below us */
1597c478bd9Sstevel@tonic-gate 	cons_polledio_t		wc_polledio; /* polled I/O function pointers */
1607c478bd9Sstevel@tonic-gate 	cons_polledio_t		*wc_kb_polledio; /* keyboard's polledio */
1617c478bd9Sstevel@tonic-gate 	unsigned int	wc_kb_getpolledio_id; /* id for kb CONSOPENPOLLEDIO */
162aecfc01dSrui zang - Sun Microsystems - Beijing China 	queue_t *wc_pending_wq;
1637c478bd9Sstevel@tonic-gate 	mblk_t	*wc_pending_link;	/* I_PLINK pending for kb polledio */
1647c478bd9Sstevel@tonic-gate } wscons;
1657c478bd9Sstevel@tonic-gate 
166aecfc01dSrui zang - Sun Microsystems - Beijing China /*
167aecfc01dSrui zang - Sun Microsystems - Beijing China  * This module has a D_MTPERMOD inner perimeter, so we don't need to protect
168aecfc01dSrui zang - Sun Microsystems - Beijing China  * the variables only shared within this module
169aecfc01dSrui zang - Sun Microsystems - Beijing China  */
170aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("D_MTPERMOD protected data", wscons))
171aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("D_MTPERMOD protected data", wscons_state))
172aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("D_MTPERMOD protected data", vt_stat))
173aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("D_MTPERMOD protected data", vc_waitactive_msg))
174aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("D_MTPERMOD protected data", tty_common))
175aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("D_MTPERMOD protected data", vt_mode))
176aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("D_MTPERMOD protected data", vt_dispinfo))
177aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("D_MTPERMOD protected data", winsize))
178aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("D_MTPERMOD protected data", vc_last_console))
179aecfc01dSrui zang - Sun Microsystems - Beijing China 
180aecfc01dSrui zang - Sun Microsystems - Beijing China #ifdef _HAVE_TEM_FIRMWARE
181aecfc01dSrui zang - Sun Microsystems - Beijing China ssize_t wc_cons_wrtvec(promif_redir_arg_t arg, uchar_t *s, size_t n);
182aecfc01dSrui zang - Sun Microsystems - Beijing China #endif /* _HAVE_TEM_FIRMWARE */
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate static int	wcopen(queue_t *, dev_t *, int, int, cred_t *);
1857c478bd9Sstevel@tonic-gate static int	wcclose(queue_t *, int, cred_t *);
186d4a54bf7SToomas Soome static int	wcuwsrv(queue_t *);
1877c478bd9Sstevel@tonic-gate static int	wcuwput(queue_t *, mblk_t *);
1887c478bd9Sstevel@tonic-gate static int	wclrput(queue_t *, mblk_t *);
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate static struct module_info wcm_info = {
1917c478bd9Sstevel@tonic-gate 	0,
1927c478bd9Sstevel@tonic-gate 	"wc",
1937c478bd9Sstevel@tonic-gate 	0,
1947c478bd9Sstevel@tonic-gate 	INFPSZ,
1957c478bd9Sstevel@tonic-gate 	2048,
1967c478bd9Sstevel@tonic-gate 	128
1977c478bd9Sstevel@tonic-gate };
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate static struct qinit wcurinit = {
2007c478bd9Sstevel@tonic-gate 	putq,
2017c478bd9Sstevel@tonic-gate 	NULL,
2027c478bd9Sstevel@tonic-gate 	wcopen,
2037c478bd9Sstevel@tonic-gate 	wcclose,
2047c478bd9Sstevel@tonic-gate 	NULL,
2057c478bd9Sstevel@tonic-gate 	&wcm_info,
2067c478bd9Sstevel@tonic-gate 	NULL
2077c478bd9Sstevel@tonic-gate };
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate static struct qinit wcuwinit = {
2107c478bd9Sstevel@tonic-gate 	wcuwput,
211d4a54bf7SToomas Soome 	wcuwsrv,
2127c478bd9Sstevel@tonic-gate 	wcopen,
2137c478bd9Sstevel@tonic-gate 	wcclose,
2147c478bd9Sstevel@tonic-gate 	NULL,
2157c478bd9Sstevel@tonic-gate 	&wcm_info,
2167c478bd9Sstevel@tonic-gate 	NULL
2177c478bd9Sstevel@tonic-gate };
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate static struct qinit wclrinit = {
2207c478bd9Sstevel@tonic-gate 	wclrput,
2217c478bd9Sstevel@tonic-gate 	NULL,
2227c478bd9Sstevel@tonic-gate 	NULL,
2237c478bd9Sstevel@tonic-gate 	NULL,
2247c478bd9Sstevel@tonic-gate 	NULL,
2257c478bd9Sstevel@tonic-gate 	&wcm_info,
2267c478bd9Sstevel@tonic-gate 	NULL
2277c478bd9Sstevel@tonic-gate };
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate /*
2307c478bd9Sstevel@tonic-gate  * We always putnext directly to the underlying queue.
2317c478bd9Sstevel@tonic-gate  */
2327c478bd9Sstevel@tonic-gate static struct qinit wclwinit = {
2337c478bd9Sstevel@tonic-gate 	NULL,
2347c478bd9Sstevel@tonic-gate 	NULL,
2357c478bd9Sstevel@tonic-gate 	NULL,
2367c478bd9Sstevel@tonic-gate 	NULL,
2377c478bd9Sstevel@tonic-gate 	NULL,
2387c478bd9Sstevel@tonic-gate 	&wcm_info,
2397c478bd9Sstevel@tonic-gate 	NULL
2407c478bd9Sstevel@tonic-gate };
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate static struct streamtab wcinfo = {
2437c478bd9Sstevel@tonic-gate 	&wcurinit,
2447c478bd9Sstevel@tonic-gate 	&wcuwinit,
2457c478bd9Sstevel@tonic-gate 	&wclrinit,
2467c478bd9Sstevel@tonic-gate 	&wclwinit,
2477c478bd9Sstevel@tonic-gate };
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate static int wc_info(dev_info_t *, ddi_info_cmd_t, void *, void **result);
2507c478bd9Sstevel@tonic-gate static int wc_attach(dev_info_t *, ddi_attach_cmd_t);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate DDI_DEFINE_STREAM_OPS(wc_ops, nulldev, nulldev, wc_attach, nodev, nodev,
25319397407SSherry Moore     wc_info, D_MTPERMOD | D_MP, &wcinfo, ddi_quiesce_not_supported);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate static void	wcreioctl(void *);
256d4a54bf7SToomas Soome static void	wcioctl(queue_t *, mblk_t *);
257fea9cb91Slq #ifdef _HAVE_TEM_FIRMWARE
2587c478bd9Sstevel@tonic-gate static void	wcopoll(void *);
259fea9cb91Slq #endif /* _HAVE_TEM_FIRMWARE */
2607c478bd9Sstevel@tonic-gate static void	wcrstrt(void *);
261aecfc01dSrui zang - Sun Microsystems - Beijing China static void	wc_open_kb_polledio(struct wscons_state *wc, queue_t *q,
262aecfc01dSrui zang - Sun Microsystems - Beijing China 		    mblk_t *mp);
263aecfc01dSrui zang - Sun Microsystems - Beijing China static void	wc_close_kb_polledio(struct wscons_state *wc, queue_t *q,
264aecfc01dSrui zang - Sun Microsystems - Beijing China 		    mblk_t *mp);
265aecfc01dSrui zang - Sun Microsystems - Beijing China static void	wc_polled_putchar(cons_polledio_arg_t arg,
266aecfc01dSrui zang - Sun Microsystems - Beijing China 			unsigned char c);
267281f0747Slt static boolean_t wc_polled_ischar(cons_polledio_arg_t arg);
268281f0747Slt static int	wc_polled_getchar(cons_polledio_arg_t arg);
269281f0747Slt static void	wc_polled_enter(cons_polledio_arg_t arg);
270281f0747Slt static void	wc_polled_exit(cons_polledio_arg_t arg);
271aecfc01dSrui zang - Sun Microsystems - Beijing China void	wc_get_size(vc_state_t *pvc);
272fea9cb91Slq static void	wc_modechg_cb(tem_modechg_cb_arg_t arg);
273d4a54bf7SToomas Soome static tem_vt_state_t wc_get_screen_tem(vc_state_t *);
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate static struct dev_ops wc_ops;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate /*
2787c478bd9Sstevel@tonic-gate  * Debug printing
2797c478bd9Sstevel@tonic-gate  */
2807c478bd9Sstevel@tonic-gate #ifndef DPRINTF
2817c478bd9Sstevel@tonic-gate #ifdef DEBUG
2827c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
2837c478bd9Sstevel@tonic-gate static void	wc_dprintf(const char *fmt, ...) __KPRINTFLIKE(1);
2847c478bd9Sstevel@tonic-gate #define	DPRINTF(l, m, args) \
2857c478bd9Sstevel@tonic-gate 	(((l) >= wc_errlevel) && ((m) & wc_errmask) ?	\
286fea9cb91Slq 		wc_dprintf args :			\
2877c478bd9Sstevel@tonic-gate 		(void) 0)
2887c478bd9Sstevel@tonic-gate /*
2897c478bd9Sstevel@tonic-gate  * Severity levels for printing
2907c478bd9Sstevel@tonic-gate  */
2917c478bd9Sstevel@tonic-gate #define	PRINT_L0	0	/* print every message */
2927c478bd9Sstevel@tonic-gate #define	PRINT_L1	1	/* debug */
2937c478bd9Sstevel@tonic-gate #define	PRINT_L2	2	/* quiet */
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate /*
2967c478bd9Sstevel@tonic-gate  * Masks
2977c478bd9Sstevel@tonic-gate  */
2987c478bd9Sstevel@tonic-gate #define	PRINT_MASK_ALL		0xFFFFFFFFU
2997c478bd9Sstevel@tonic-gate uint_t	wc_errmask = PRINT_MASK_ALL;
3007c478bd9Sstevel@tonic-gate uint_t	wc_errlevel = PRINT_L2;
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate #else
3037c478bd9Sstevel@tonic-gate #define	DPRINTF(l, m, args)	/* NOTHING */
3047c478bd9Sstevel@tonic-gate #endif
3057c478bd9Sstevel@tonic-gate #endif
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
3097c478bd9Sstevel@tonic-gate  */
3107c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
3117c478bd9Sstevel@tonic-gate 	&mod_driverops, /* Type of module.  This one is a pseudo driver */
31219397407SSherry Moore 	"Workstation multiplexer Driver 'wc'",
3137c478bd9Sstevel@tonic-gate 	&wc_ops,	/* driver ops */
3147c478bd9Sstevel@tonic-gate };
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
3177c478bd9Sstevel@tonic-gate 	MODREV_1,
3187c478bd9Sstevel@tonic-gate 	&modldrv,
3197c478bd9Sstevel@tonic-gate 	NULL
3207c478bd9Sstevel@tonic-gate };
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate int
_init(void)3237c478bd9Sstevel@tonic-gate _init(void)
3247c478bd9Sstevel@tonic-gate {
325aecfc01dSrui zang - Sun Microsystems - Beijing China 	int rc;
326aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((rc = mod_install(&modlinkage)) == 0)
327aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_init();
328aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (rc);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate int
_fini(void)3327c478bd9Sstevel@tonic-gate _fini(void)
3337c478bd9Sstevel@tonic-gate {
3347c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)3387c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
3397c478bd9Sstevel@tonic-gate {
3407c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3447c478bd9Sstevel@tonic-gate static int
wc_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)3457c478bd9Sstevel@tonic-gate wc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
3467c478bd9Sstevel@tonic-gate {
347aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* create minor node for workstation hard console */
3487c478bd9Sstevel@tonic-gate 	if (ddi_create_minor_node(devi, "wscons", S_IFCHR,
349*7edfb5b0SToomas Soome 	    0, DDI_PSEUDO, 0) == DDI_FAILURE) {
3507c478bd9Sstevel@tonic-gate 		ddi_remove_minor_node(devi, NULL);
351aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
3527c478bd9Sstevel@tonic-gate 	}
353aecfc01dSrui zang - Sun Microsystems - Beijing China 
354aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&vc_lock);
355aecfc01dSrui zang - Sun Microsystems - Beijing China 
3567c478bd9Sstevel@tonic-gate 	wc_dip = devi;
357fea9cb91Slq 
358fea9cb91Slq 	bzero(&(wscons.wc_polledio), sizeof (wscons.wc_polledio));
359fea9cb91Slq 
360aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_resize(VC_DEFAULT_COUNT);
361aecfc01dSrui zang - Sun Microsystems - Beijing China 
362aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&vc_lock);
363aecfc01dSrui zang - Sun Microsystems - Beijing China 
3647c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate /* ARGSUSED */
3687c478bd9Sstevel@tonic-gate static int
wc_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)3697c478bd9Sstevel@tonic-gate wc_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
370d4a54bf7SToomas Soome     void **result)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate 	int error;
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	switch (infocmd) {
3757c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
3767c478bd9Sstevel@tonic-gate 		if (wc_dip == NULL) {
3777c478bd9Sstevel@tonic-gate 			error = DDI_FAILURE;
3787c478bd9Sstevel@tonic-gate 		} else {
3797c478bd9Sstevel@tonic-gate 			*result = (void *) wc_dip;
3807c478bd9Sstevel@tonic-gate 			error = DDI_SUCCESS;
3817c478bd9Sstevel@tonic-gate 		}
3827c478bd9Sstevel@tonic-gate 		break;
3837c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
3847c478bd9Sstevel@tonic-gate 		*result = (void *)0;
3857c478bd9Sstevel@tonic-gate 		error = DDI_SUCCESS;
3867c478bd9Sstevel@tonic-gate 		break;
3877c478bd9Sstevel@tonic-gate 	default:
3887c478bd9Sstevel@tonic-gate 		error = DDI_FAILURE;
3897c478bd9Sstevel@tonic-gate 	}
3907c478bd9Sstevel@tonic-gate 	return (error);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate 
393aecfc01dSrui zang - Sun Microsystems - Beijing China static void
wc_init_polledio(void)394aecfc01dSrui zang - Sun Microsystems - Beijing China wc_init_polledio(void)
3957c478bd9Sstevel@tonic-gate {
396fea9cb91Slq 	static boolean_t polledio_inited = B_FALSE;
397aecfc01dSrui zang - Sun Microsystems - Beijing China 	_NOTE(SCHEME_PROTECTS_DATA("D_MTPERMOD protected data",
398aecfc01dSrui zang - Sun Microsystems - Beijing China 	    polledio_inited))
3997c478bd9Sstevel@tonic-gate 
400aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (polledio_inited)
401aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
4027c478bd9Sstevel@tonic-gate 
403aecfc01dSrui zang - Sun Microsystems - Beijing China 	polledio_inited = B_TRUE;
4047c478bd9Sstevel@tonic-gate 
405aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
406aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Initialize the parts of the polled I/O struct that
407aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * are common to both input and output modes, but which
408aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * don't flag to the upper layers, which if any of the
409aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * two modes are available.  We don't know at this point
410aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * if system is configured CONS_KFB, but we will when
411aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * consconfig_dacf asks us with CONSOPENPOLLED I/O.
412aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
413aecfc01dSrui zang - Sun Microsystems - Beijing China 	bzero(&(wscons.wc_polledio), sizeof (wscons.wc_polledio));
414aecfc01dSrui zang - Sun Microsystems - Beijing China 	wscons.wc_polledio.cons_polledio_version =
415aecfc01dSrui zang - Sun Microsystems - Beijing China 	    CONSPOLLEDIO_V0;
416aecfc01dSrui zang - Sun Microsystems - Beijing China 	wscons.wc_polledio.cons_polledio_argument =
417aecfc01dSrui zang - Sun Microsystems - Beijing China 	    (cons_polledio_arg_t)&wscons;
418aecfc01dSrui zang - Sun Microsystems - Beijing China 	wscons.wc_polledio.cons_polledio_enter =
419aecfc01dSrui zang - Sun Microsystems - Beijing China 	    wc_polled_enter;
420aecfc01dSrui zang - Sun Microsystems - Beijing China 	wscons.wc_polledio.cons_polledio_exit =
421aecfc01dSrui zang - Sun Microsystems - Beijing China 	    wc_polled_exit;
422fea9cb91Slq 
423fea9cb91Slq #ifdef _HAVE_TEM_FIRMWARE
424aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
425aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * If we're talking directly to a framebuffer, we assume
426aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * that it's a "slow" device, so that rendering should
427aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * be deferred to a timeout or softcall so that we write
428aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * a bunch of characters at once.
429aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
430aecfc01dSrui zang - Sun Microsystems - Beijing China 	wscons.wc_defer_output = prom_stdout_is_framebuffer();
431fea9cb91Slq #endif /* _HAVE_TEM_FIRMWARE */
432aecfc01dSrui zang - Sun Microsystems - Beijing China }
4337c478bd9Sstevel@tonic-gate 
434aecfc01dSrui zang - Sun Microsystems - Beijing China /*ARGSUSED*/
435aecfc01dSrui zang - Sun Microsystems - Beijing China static int
wcopen(queue_t * q,dev_t * devp,int flag,int sflag,cred_t * crp)436aecfc01dSrui zang - Sun Microsystems - Beijing China wcopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
437aecfc01dSrui zang - Sun Microsystems - Beijing China {
438aecfc01dSrui zang - Sun Microsystems - Beijing China 	int minor;
439aecfc01dSrui zang - Sun Microsystems - Beijing China 
440aecfc01dSrui zang - Sun Microsystems - Beijing China 	wc_init_polledio();
441aecfc01dSrui zang - Sun Microsystems - Beijing China 	minor = (int)getminor(*devp);
442aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (vt_open(minor, q, crp));
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4467c478bd9Sstevel@tonic-gate static int
wcclose(queue_t * q,int flag,cred_t * crp)4477c478bd9Sstevel@tonic-gate wcclose(queue_t *q, int flag, cred_t *crp)
4487c478bd9Sstevel@tonic-gate {
449aecfc01dSrui zang - Sun Microsystems - Beijing China 	vc_state_t *pvc = (vc_state_t *)q->q_ptr;
450aecfc01dSrui zang - Sun Microsystems - Beijing China 
4517c478bd9Sstevel@tonic-gate 	qprocsoff(q);
452aecfc01dSrui zang - Sun Microsystems - Beijing China 
453aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&vc_lock);
454aecfc01dSrui zang - Sun Microsystems - Beijing China 
455ceeba6f9Srui zang - Sun Microsystems - Beijing China 	/*
456ceeba6f9Srui zang - Sun Microsystems - Beijing China 	 * If we are closing the VT node which
457ceeba6f9Srui zang - Sun Microsystems - Beijing China 	 * /dev/vt/console_user points to, revert
458ceeba6f9Srui zang - Sun Microsystems - Beijing China 	 * /dev/vt/console to /dev/console
459ceeba6f9Srui zang - Sun Microsystems - Beijing China 	 */
460ceeba6f9Srui zang - Sun Microsystems - Beijing China 	if (vc_cons_user == pvc->vc_minor)
461ceeba6f9Srui zang - Sun Microsystems - Beijing China 		vc_cons_user = VT_MINOR_INVALID;
462ceeba6f9Srui zang - Sun Microsystems - Beijing China 
463aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pvc->vc_minor == 0 || pvc->vc_minor == vc_active_console) {
464aecfc01dSrui zang - Sun Microsystems - Beijing China 
465aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
466aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * If we lose the system console,
467aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * no any other active consoles.
468aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
469aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (pvc->vc_minor == 0 && pvc->vc_minor == vc_active_console) {
470aecfc01dSrui zang - Sun Microsystems - Beijing China 			vc_active_console = VT_MINOR_INVALID;
471aecfc01dSrui zang - Sun Microsystems - Beijing China 			vc_last_console = VT_MINOR_INVALID;
472aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
473aecfc01dSrui zang - Sun Microsystems - Beijing China 
474aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
475aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * just clean for our primary console
476aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * and active console
477aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
478aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_enter(&pvc->vc_state_lock);
479aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_clean(q, pvc);
480aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&pvc->vc_state_lock);
481aecfc01dSrui zang - Sun Microsystems - Beijing China 
482aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&vc_lock);
483aecfc01dSrui zang - Sun Microsystems - Beijing China 
484aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (0);
4857c478bd9Sstevel@tonic-gate 	}
486aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_close(q, pvc, crp);
487aecfc01dSrui zang - Sun Microsystems - Beijing China 
488aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&vc_lock);
489aecfc01dSrui zang - Sun Microsystems - Beijing China 
4907c478bd9Sstevel@tonic-gate 	return (0);
4917c478bd9Sstevel@tonic-gate }
4927c478bd9Sstevel@tonic-gate 
493d4a54bf7SToomas Soome /*
494d4a54bf7SToomas Soome  * Service procedure for upper write queue.
495d4a54bf7SToomas Soome  * We need to have service procedure to make sure the keyboard events
496d4a54bf7SToomas Soome  * are queued up for screen output and are not dependant on the screen
497d4a54bf7SToomas Soome  * updates.
498d4a54bf7SToomas Soome  */
499d4a54bf7SToomas Soome static int
wcuwsrv(queue_t * q)500d4a54bf7SToomas Soome wcuwsrv(queue_t *q)
501d4a54bf7SToomas Soome {
502d4a54bf7SToomas Soome 	vc_state_t *pvc = (vc_state_t *)q->q_ptr;
503d4a54bf7SToomas Soome 	tem_vt_state_t ptem = NULL;
504d4a54bf7SToomas Soome 	mblk_t *mp;
505d4a54bf7SToomas Soome 	ssize_t cc;
506d4a54bf7SToomas Soome 
507d4a54bf7SToomas Soome 	while ((mp = getq(q)) != NULL) {
508d4a54bf7SToomas Soome 		/*
509d4a54bf7SToomas Soome 		 * If we're waiting for something to happen (delay timeout to
510d4a54bf7SToomas Soome 		 * expire, current transmission to finish, output to be
511d4a54bf7SToomas Soome 		 * restarted, output to finish draining), don't grab anything
512d4a54bf7SToomas Soome 		 * new.
513d4a54bf7SToomas Soome 		 */
514d4a54bf7SToomas Soome 		if (pvc->vc_flags & (WCS_DELAY|WCS_BUSY|WCS_STOPPED)) {
51536d47380SJohn Levon 			(void) putbq(q, mp);
516d4a54bf7SToomas Soome 			return (0);
517d4a54bf7SToomas Soome 		}
518d4a54bf7SToomas Soome 
519d4a54bf7SToomas Soome 		switch (mp->b_datap->db_type) {
520d4a54bf7SToomas Soome 		default:	/* drop unknown type */
521d4a54bf7SToomas Soome 			freemsg(mp);
522d4a54bf7SToomas Soome 			continue;
523d4a54bf7SToomas Soome 
524d4a54bf7SToomas Soome 		case M_IOCTL:
525d4a54bf7SToomas Soome 			wcioctl(q, mp);
526d4a54bf7SToomas Soome 			continue;
527d4a54bf7SToomas Soome 
528d4a54bf7SToomas Soome 		case M_DELAY:
529d4a54bf7SToomas Soome 			/*
530d4a54bf7SToomas Soome 			 * Arrange for "wcrstrt" to be called when the
531d4a54bf7SToomas Soome 			 * delay expires; it will turn WCS_DELAY off.
532d4a54bf7SToomas Soome 			 */
533d4a54bf7SToomas Soome 			if (pvc->vc_timeoutid != 0)
534d4a54bf7SToomas Soome 				(void) quntimeout(q, pvc->vc_timeoutid);
535d4a54bf7SToomas Soome 			pvc->vc_timeoutid = qtimeout(q, wcrstrt, pvc,
536d4a54bf7SToomas Soome 			    (clock_t)(*(unsigned char *)mp->b_rptr + 6));
537d4a54bf7SToomas Soome 
538d4a54bf7SToomas Soome 			mutex_enter(&pvc->vc_state_lock);
539d4a54bf7SToomas Soome 			pvc->vc_flags |= WCS_DELAY;
540d4a54bf7SToomas Soome 			mutex_exit(&pvc->vc_state_lock);
541d4a54bf7SToomas Soome 
542d4a54bf7SToomas Soome 			freemsg(mp);
543d4a54bf7SToomas Soome 			continue;
544d4a54bf7SToomas Soome 
545d4a54bf7SToomas Soome 		case M_DATA:
546d4a54bf7SToomas Soome 			break;
547d4a54bf7SToomas Soome 		}
548d4a54bf7SToomas Soome 
549d4a54bf7SToomas Soome 		if ((cc = mp->b_wptr - mp->b_rptr) == 0) {
550d4a54bf7SToomas Soome 			freemsg(mp);
551d4a54bf7SToomas Soome 			continue;
552d4a54bf7SToomas Soome 		}
553d4a54bf7SToomas Soome 
554d4a54bf7SToomas Soome #ifdef _HAVE_TEM_FIRMWARE
555d4a54bf7SToomas Soome 		if (consmode == CONS_KFB) {
556d4a54bf7SToomas Soome #endif /* _HAVE_TEM_FIRMWARE */
557d4a54bf7SToomas Soome 			ptem = wc_get_screen_tem(pvc);
558d4a54bf7SToomas Soome 
559d4a54bf7SToomas Soome 			if (ptem == NULL) {
560d4a54bf7SToomas Soome 				freemsg(mp);
561d4a54bf7SToomas Soome 				continue;
562d4a54bf7SToomas Soome 			}
563d4a54bf7SToomas Soome 
564d4a54bf7SToomas Soome 			for (mblk_t *nbp = mp; nbp != NULL; nbp = nbp->b_cont) {
565d4a54bf7SToomas Soome 				cc = nbp->b_wptr - nbp->b_rptr;
566d4a54bf7SToomas Soome 
567d4a54bf7SToomas Soome 				if (cc <= 0)
568d4a54bf7SToomas Soome 					continue;
569d4a54bf7SToomas Soome 
570d4a54bf7SToomas Soome 				tem_write(ptem, nbp->b_rptr, cc, kcred);
571d4a54bf7SToomas Soome 			}
572d4a54bf7SToomas Soome 			freemsg(mp);
573d4a54bf7SToomas Soome #ifdef _HAVE_TEM_FIRMWARE
574d4a54bf7SToomas Soome 			continue;
575d4a54bf7SToomas Soome 		}
576d4a54bf7SToomas Soome 
577d4a54bf7SToomas Soome 		/* consmode = CONS_FW */
578d4a54bf7SToomas Soome 		if (pvc->vc_minor != 0) {
579d4a54bf7SToomas Soome 			freemsg(mp);
580d4a54bf7SToomas Soome 			continue;
581d4a54bf7SToomas Soome 		}
582d4a54bf7SToomas Soome 
583d4a54bf7SToomas Soome 		/*
584d4a54bf7SToomas Soome 		 * Direct output to the frame buffer if this device
585d4a54bf7SToomas Soome 		 * is not the "hardware" console.
586d4a54bf7SToomas Soome 		 */
587d4a54bf7SToomas Soome 		if (wscons.wc_defer_output) {
588d4a54bf7SToomas Soome 			mutex_enter(&pvc->vc_state_lock);
589d4a54bf7SToomas Soome 			pvc->vc_flags |= WCS_BUSY;
590d4a54bf7SToomas Soome 			mutex_exit(&pvc->vc_state_lock);
591d4a54bf7SToomas Soome 
592d4a54bf7SToomas Soome 			pvc->vc_pendc = -1;
593d4a54bf7SToomas Soome 
594d4a54bf7SToomas Soome 			for (mblk_t *nbp = mp; nbp != NULL; nbp = nbp->b_cont) {
595d4a54bf7SToomas Soome 				cc = nbp->b_wptr - nbp->b_rptr;
596d4a54bf7SToomas Soome 
597d4a54bf7SToomas Soome 				if (cc <= 0)
598d4a54bf7SToomas Soome 					continue;
599d4a54bf7SToomas Soome 
600d4a54bf7SToomas Soome 				console_puts((const char *)nbp->b_rptr, cc);
601d4a54bf7SToomas Soome 			}
602d4a54bf7SToomas Soome 			freemsg(mp);
603d4a54bf7SToomas Soome 			mutex_enter(&pvc->vc_state_lock);
604d4a54bf7SToomas Soome 			pvc->vc_flags &= ~WCS_BUSY;
605d4a54bf7SToomas Soome 			mutex_exit(&pvc->vc_state_lock);
606d4a54bf7SToomas Soome 			continue;
607d4a54bf7SToomas Soome 		}
608d4a54bf7SToomas Soome 		for (boolean_t done = B_FALSE; done != B_TRUE; ) {
609d4a54bf7SToomas Soome 			int c;
610d4a54bf7SToomas Soome 
611d4a54bf7SToomas Soome 			c = *mp->b_rptr++;
612d4a54bf7SToomas Soome 			cc--;
613d4a54bf7SToomas Soome 			if (prom_mayput((char)c) != 0) {
614d4a54bf7SToomas Soome 
615d4a54bf7SToomas Soome 				mutex_enter(&pvc->vc_state_lock);
616d4a54bf7SToomas Soome 				pvc->vc_flags |= WCS_BUSY;
617d4a54bf7SToomas Soome 				mutex_exit(&pvc->vc_state_lock);
618d4a54bf7SToomas Soome 
619d4a54bf7SToomas Soome 				pvc->vc_pendc = c;
620d4a54bf7SToomas Soome 				if (pvc->vc_timeoutid != 0)
621d4a54bf7SToomas Soome 					(void) quntimeout(q,
622d4a54bf7SToomas Soome 					    pvc->vc_timeoutid);
623d4a54bf7SToomas Soome 				pvc->vc_timeoutid = qtimeout(q, wcopoll,
624d4a54bf7SToomas Soome 				    pvc, 1);
625d4a54bf7SToomas Soome 				if (mp != NULL) {
626d4a54bf7SToomas Soome 					/* not done with this message yet */
627d4a54bf7SToomas Soome 					(void) putbq(q, mp);
628d4a54bf7SToomas Soome 					return (0);
629d4a54bf7SToomas Soome 				}
630d4a54bf7SToomas Soome 				break;
631d4a54bf7SToomas Soome 			}
632d4a54bf7SToomas Soome 			while (cc <= 0) {
633d4a54bf7SToomas Soome 				mblk_t *nbp = mp;
634d4a54bf7SToomas Soome 				mp = mp->b_cont;
635d4a54bf7SToomas Soome 				freeb(nbp);
636d4a54bf7SToomas Soome 				if (mp == NULL) {
637d4a54bf7SToomas Soome 					done = B_TRUE;
638d4a54bf7SToomas Soome 					break;
639d4a54bf7SToomas Soome 				}
640d4a54bf7SToomas Soome 				/* LINTED E_PTRDIFF_OVERFLOW */
641d4a54bf7SToomas Soome 				cc = mp->b_wptr - mp->b_rptr;
642d4a54bf7SToomas Soome 			}
643d4a54bf7SToomas Soome 		}
644d4a54bf7SToomas Soome #endif /* _HAVE_TEM_FIRMWARE */
645d4a54bf7SToomas Soome 	}
646d4a54bf7SToomas Soome 	return (0);
647d4a54bf7SToomas Soome }
648d4a54bf7SToomas Soome 
6497c478bd9Sstevel@tonic-gate /*
6507c478bd9Sstevel@tonic-gate  * Put procedure for upper write queue.
6517c478bd9Sstevel@tonic-gate  * Respond to M_STOP, M_START, M_IOCTL, and M_FLUSH messages here;
6527c478bd9Sstevel@tonic-gate  * queue up M_BREAK, M_DELAY, and M_DATA messages for processing by
653d4a54bf7SToomas Soome  * the service routine. Discard everything else.
6547c478bd9Sstevel@tonic-gate  */
6557c478bd9Sstevel@tonic-gate static int
wcuwput(queue_t * q,mblk_t * mp)6567c478bd9Sstevel@tonic-gate wcuwput(queue_t *q, mblk_t *mp)
6577c478bd9Sstevel@tonic-gate {
658aecfc01dSrui zang - Sun Microsystems - Beijing China 	vc_state_t *pvc = (vc_state_t *)q->q_ptr;
659aecfc01dSrui zang - Sun Microsystems - Beijing China 
6607c478bd9Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	case M_STOP:
663aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_enter(&pvc->vc_state_lock);
664aecfc01dSrui zang - Sun Microsystems - Beijing China 		pvc->vc_flags |= WCS_STOPPED;
665aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&pvc->vc_state_lock);
666aecfc01dSrui zang - Sun Microsystems - Beijing China 
6677c478bd9Sstevel@tonic-gate 		freemsg(mp);
6687c478bd9Sstevel@tonic-gate 		break;
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	case M_START:
671aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_enter(&pvc->vc_state_lock);
672aecfc01dSrui zang - Sun Microsystems - Beijing China 		pvc->vc_flags &= ~WCS_STOPPED;
673aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&pvc->vc_state_lock);
674aecfc01dSrui zang - Sun Microsystems - Beijing China 
675d4a54bf7SToomas Soome 		qenable(q);
6767c478bd9Sstevel@tonic-gate 		freemsg(mp);
6777c478bd9Sstevel@tonic-gate 		break;
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 	case M_IOCTL: {
6807c478bd9Sstevel@tonic-gate 		struct iocblk *iocp;
6817c478bd9Sstevel@tonic-gate 		struct linkblk *linkp;
6827c478bd9Sstevel@tonic-gate 
683aecfc01dSrui zang - Sun Microsystems - Beijing China 		iocp = (struct iocblk *)(void *)mp->b_rptr;
6847c478bd9Sstevel@tonic-gate 		switch (iocp->ioc_cmd) {
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 		case I_LINK:	/* stupid, but permitted */
6877c478bd9Sstevel@tonic-gate 		case I_PLINK:
6887c478bd9Sstevel@tonic-gate 			if (wscons.wc_kbdqueue != NULL) {
6897c478bd9Sstevel@tonic-gate 				/* somebody already linked */
6907c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, EINVAL);
6917c478bd9Sstevel@tonic-gate 				return (0);
6927c478bd9Sstevel@tonic-gate 			}
693aecfc01dSrui zang - Sun Microsystems - Beijing China 			linkp = (struct linkblk *)(void *)mp->b_cont->b_rptr;
6947c478bd9Sstevel@tonic-gate 			wscons.wc_kbdqueue = WR(linkp->l_qbot);
6957c478bd9Sstevel@tonic-gate 			mp->b_datap->db_type = M_IOCACK;
6967c478bd9Sstevel@tonic-gate 			iocp->ioc_count = 0;
6977c478bd9Sstevel@tonic-gate 			wc_open_kb_polledio(&wscons, q, mp);
6987c478bd9Sstevel@tonic-gate 			break;
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 		case I_UNLINK:	/* stupid, but permitted */
7017c478bd9Sstevel@tonic-gate 		case I_PUNLINK:
702aecfc01dSrui zang - Sun Microsystems - Beijing China 			linkp = (struct linkblk *)(void *)mp->b_cont->b_rptr;
7037c478bd9Sstevel@tonic-gate 			if (wscons.wc_kbdqueue != WR(linkp->l_qbot)) {
7047c478bd9Sstevel@tonic-gate 				/* not us */
7057c478bd9Sstevel@tonic-gate 				miocnak(q, mp, 0, EINVAL);
7067c478bd9Sstevel@tonic-gate 				return (0);
7077c478bd9Sstevel@tonic-gate 			}
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 			mp->b_datap->db_type = M_IOCACK;
7107c478bd9Sstevel@tonic-gate 			iocp->ioc_count = 0;
7117c478bd9Sstevel@tonic-gate 			wc_close_kb_polledio(&wscons, q, mp);
7127c478bd9Sstevel@tonic-gate 			break;
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 		case TCSETSW:
7157c478bd9Sstevel@tonic-gate 		case TCSETSF:
7167c478bd9Sstevel@tonic-gate 		case TCSETAW:
7177c478bd9Sstevel@tonic-gate 		case TCSETAF:
7187c478bd9Sstevel@tonic-gate 		case TCSBRK:
7197c478bd9Sstevel@tonic-gate 			/*
7207c478bd9Sstevel@tonic-gate 			 * The changes do not take effect until all
7217c478bd9Sstevel@tonic-gate 			 * output queued before them is drained.
7227c478bd9Sstevel@tonic-gate 			 * Put this message on the queue, so that
723d4a54bf7SToomas Soome 			 * "wcuwsrv" will see it when it's done
724d4a54bf7SToomas Soome 			 * with the output before it.
7257c478bd9Sstevel@tonic-gate 			 */
726d4a54bf7SToomas Soome 			if (putq(q, mp) == 0)
727d4a54bf7SToomas Soome 				freemsg(mp);
7287c478bd9Sstevel@tonic-gate 			break;
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 		case CONSSETABORTENABLE:
7317c478bd9Sstevel@tonic-gate 		case CONSGETABORTENABLE:
7327c478bd9Sstevel@tonic-gate 		case KIOCSDIRECT:
7337c478bd9Sstevel@tonic-gate 			if (wscons.wc_kbdqueue != NULL) {
734aecfc01dSrui zang - Sun Microsystems - Beijing China 				wscons.wc_pending_wq = q;
7357c478bd9Sstevel@tonic-gate 				(void) putnext(wscons.wc_kbdqueue, mp);
7367c478bd9Sstevel@tonic-gate 				break;
7377c478bd9Sstevel@tonic-gate 			}
7387c478bd9Sstevel@tonic-gate 			/* fall through */
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 		default:
7417c478bd9Sstevel@tonic-gate 			/*
7427c478bd9Sstevel@tonic-gate 			 * Do it now.
7437c478bd9Sstevel@tonic-gate 			 */
7447c478bd9Sstevel@tonic-gate 			wcioctl(q, mp);
7457c478bd9Sstevel@tonic-gate 			break;
7467c478bd9Sstevel@tonic-gate 		}
7477c478bd9Sstevel@tonic-gate 		break;
7487c478bd9Sstevel@tonic-gate 	}
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	case M_FLUSH:
7517c478bd9Sstevel@tonic-gate 		if (*mp->b_rptr & FLUSHW) {
7527c478bd9Sstevel@tonic-gate 			/*
7537c478bd9Sstevel@tonic-gate 			 * Flush our write queue.
7547c478bd9Sstevel@tonic-gate 			 */
7557c478bd9Sstevel@tonic-gate 			flushq(q, FLUSHDATA);	/* XXX doesn't flush M_DELAY */
7567c478bd9Sstevel@tonic-gate 			*mp->b_rptr &= ~FLUSHW;	/* it has been flushed */
7577c478bd9Sstevel@tonic-gate 		}
7587c478bd9Sstevel@tonic-gate 		if (*mp->b_rptr & FLUSHR) {
7597c478bd9Sstevel@tonic-gate 			flushq(RD(q), FLUSHDATA);
7607c478bd9Sstevel@tonic-gate 			qreply(q, mp);	/* give the read queues a crack at it */
7617c478bd9Sstevel@tonic-gate 		} else
7627c478bd9Sstevel@tonic-gate 			freemsg(mp);
7637c478bd9Sstevel@tonic-gate 		break;
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	case M_BREAK:
7667c478bd9Sstevel@tonic-gate 		/*
7677c478bd9Sstevel@tonic-gate 		 * Ignore these, as they make no sense.
7687c478bd9Sstevel@tonic-gate 		 */
7697c478bd9Sstevel@tonic-gate 		freemsg(mp);
7707c478bd9Sstevel@tonic-gate 		break;
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 	case M_DELAY:
7737c478bd9Sstevel@tonic-gate 	case M_DATA:
7747c478bd9Sstevel@tonic-gate 		/*
775d4a54bf7SToomas Soome 		 * Queue the message up to be transmitted.
7767c478bd9Sstevel@tonic-gate 		 */
777d4a54bf7SToomas Soome 		if (putq(q, mp) == 0)
778d4a54bf7SToomas Soome 			freemsg(mp);
779aecfc01dSrui zang - Sun Microsystems - Beijing China 		break;
780aecfc01dSrui zang - Sun Microsystems - Beijing China 
781aecfc01dSrui zang - Sun Microsystems - Beijing China 	case M_IOCDATA:
782aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_miocdata(q, mp);
7837c478bd9Sstevel@tonic-gate 		break;
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	default:
7867c478bd9Sstevel@tonic-gate 		/*
7877c478bd9Sstevel@tonic-gate 		 * "No, I don't want a subscription to Chain Store Age,
7887c478bd9Sstevel@tonic-gate 		 * thank you anyway."
7897c478bd9Sstevel@tonic-gate 		 */
7907c478bd9Sstevel@tonic-gate 		freemsg(mp);
7917c478bd9Sstevel@tonic-gate 		break;
7927c478bd9Sstevel@tonic-gate 	}
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	return (0);
7957c478bd9Sstevel@tonic-gate }
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate /*
7987c478bd9Sstevel@tonic-gate  * Retry an "ioctl", now that "qbufcall" claims we may be able to allocate
7997c478bd9Sstevel@tonic-gate  * the buffer we need.
8007c478bd9Sstevel@tonic-gate  */
8017c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8027c478bd9Sstevel@tonic-gate static void
wcreioctl(void * arg)8037c478bd9Sstevel@tonic-gate wcreioctl(void *arg)
8047c478bd9Sstevel@tonic-gate {
805aecfc01dSrui zang - Sun Microsystems - Beijing China 	vc_state_t *pvc = (vc_state_t *)arg;
8067c478bd9Sstevel@tonic-gate 	queue_t *q;
8077c478bd9Sstevel@tonic-gate 	mblk_t *mp;
8087c478bd9Sstevel@tonic-gate 
809aecfc01dSrui zang - Sun Microsystems - Beijing China 	pvc->vc_bufcallid = 0;
810aecfc01dSrui zang - Sun Microsystems - Beijing China 	q = pvc->vc_ttycommon.t_writeq;
811aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((mp = pvc->vc_ttycommon.t_iocpending) != NULL) {
8127c478bd9Sstevel@tonic-gate 		/* not pending any more */
813aecfc01dSrui zang - Sun Microsystems - Beijing China 		pvc->vc_ttycommon.t_iocpending = NULL;
8147c478bd9Sstevel@tonic-gate 		wcioctl(q, mp);
8157c478bd9Sstevel@tonic-gate 	}
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate 
818fea9cb91Slq static int
wc_getterm(mblk_t * mp)819fea9cb91Slq wc_getterm(mblk_t *mp)
820fea9cb91Slq {
821fea9cb91Slq 	char *term;
822fea9cb91Slq 	intptr_t arg;
82322eb7cb5Sgd 	int flag = ((struct iocblk *)(void *)mp->b_rptr)->ioc_flag;
824fea9cb91Slq 
825fea9cb91Slq 	STRUCT_DECL(cons_getterm, wcterm);
826fea9cb91Slq 	STRUCT_INIT(wcterm, flag);
827fea9cb91Slq 
82822eb7cb5Sgd 	arg = *((intptr_t *)(void *)mp->b_cont->b_rptr);
829fea9cb91Slq 
830fea9cb91Slq 	if (ddi_copyin((void *)arg, STRUCT_BUF(wcterm),
831fea9cb91Slq 	    STRUCT_SIZE(wcterm), flag) != 0) {
832fea9cb91Slq 		return (EFAULT);
833fea9cb91Slq 	}
834fea9cb91Slq 
835fea9cb91Slq 	if (consmode == CONS_FW) {
836fea9cb91Slq 		/* PROM terminal emulator */
837fea9cb91Slq 		term = "sun";
838fea9cb91Slq 	} else {
839fea9cb91Slq 		/* Kernel terminal emulator */
840fea9cb91Slq 		ASSERT(consmode == CONS_KFB);
841fea9cb91Slq 		term = "sun-color";
842fea9cb91Slq 	}
843fea9cb91Slq 
844fea9cb91Slq 	if (STRUCT_FGET(wcterm, cn_term_len) <
845fea9cb91Slq 	    strlen(term) + 1) {
846fea9cb91Slq 		return (EOVERFLOW);
847fea9cb91Slq 	}
848fea9cb91Slq 
849fea9cb91Slq 	if (ddi_copyout(term,
850fea9cb91Slq 	    STRUCT_FGETP(wcterm, cn_term_type),
851fea9cb91Slq 	    strlen(term) + 1, flag) != 0) {
852fea9cb91Slq 		return (EFAULT);
853fea9cb91Slq 	}
854fea9cb91Slq 
855fea9cb91Slq 	return (0);
856fea9cb91Slq }
857fea9cb91Slq 
8587c478bd9Sstevel@tonic-gate /*
8597c478bd9Sstevel@tonic-gate  * Process an "ioctl" message sent down to us.
8607c478bd9Sstevel@tonic-gate  */
8617c478bd9Sstevel@tonic-gate static void
wcioctl(queue_t * q,mblk_t * mp)8627c478bd9Sstevel@tonic-gate wcioctl(queue_t *q, mblk_t *mp)
8637c478bd9Sstevel@tonic-gate {
864aecfc01dSrui zang - Sun Microsystems - Beijing China 	vc_state_t *pvc = (vc_state_t *)q->q_ptr;
8657c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;
8667c478bd9Sstevel@tonic-gate 	size_t datasize;
8677c478bd9Sstevel@tonic-gate 	int error;
868fea9cb91Slq 	long len;
8697c478bd9Sstevel@tonic-gate 
870aecfc01dSrui zang - Sun Microsystems - Beijing China 	iocp = (struct iocblk *)(void *)mp->b_rptr;
871aecfc01dSrui zang - Sun Microsystems - Beijing China 
872aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((iocp->ioc_cmd & VTIOC) == VTIOC ||
873aecfc01dSrui zang - Sun Microsystems - Beijing China 	    (iocp->ioc_cmd & KDIOC) == KDIOC) {
874aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_ioctl(q, mp);
875aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
876aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 	switch (iocp->ioc_cmd) {
8797c478bd9Sstevel@tonic-gate 	case TIOCSWINSZ:
8807c478bd9Sstevel@tonic-gate 		/*
8817c478bd9Sstevel@tonic-gate 		 * Ignore all attempts to set the screen size; the
8827c478bd9Sstevel@tonic-gate 		 * value in the EEPROM is guaranteed (modulo PROM bugs)
8837c478bd9Sstevel@tonic-gate 		 * to be the value used by the PROM monitor code, so it
8847c478bd9Sstevel@tonic-gate 		 * is by definition correct.  Many programs (e.g.,
8857c478bd9Sstevel@tonic-gate 		 * "login" and "tset") will attempt to reset the size
8867c478bd9Sstevel@tonic-gate 		 * to (0, 0) or (34, 80), neither of which is
8877c478bd9Sstevel@tonic-gate 		 * necessarily correct.
8887c478bd9Sstevel@tonic-gate 		 * We just ACK the message, so as not to disturb
8897c478bd9Sstevel@tonic-gate 		 * programs that set the sizes.
8907c478bd9Sstevel@tonic-gate 		 */
8917c478bd9Sstevel@tonic-gate 		iocp->ioc_count = 0;	/* no data returned */
8927c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_IOCACK;
8937c478bd9Sstevel@tonic-gate 		qreply(q, mp);
8947c478bd9Sstevel@tonic-gate 		return;
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 	case CONSOPENPOLLEDIO:
8977c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L1, PRINT_MASK_ALL,
89822eb7cb5Sgd 		    ("wcioctl: CONSOPENPOLLEDIO\n"));
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 		error = miocpullup(mp, sizeof (struct cons_polledio *));
9017c478bd9Sstevel@tonic-gate 		if (error != 0) {
9027c478bd9Sstevel@tonic-gate 			miocnak(q, mp, 0, error);
9037c478bd9Sstevel@tonic-gate 			return;
9047c478bd9Sstevel@tonic-gate 		}
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 		/*
907fea9cb91Slq 		 * We are given an appropriate-sized data block,
908fea9cb91Slq 		 * and return a pointer to our structure in it.
9097c478bd9Sstevel@tonic-gate 		 */
910fea9cb91Slq 		if (consmode == CONS_KFB)
911fea9cb91Slq 			wscons.wc_polledio.cons_polledio_putchar =
912fea9cb91Slq 			    wc_polled_putchar;
91322eb7cb5Sgd 		*(struct cons_polledio **)(void *)mp->b_cont->b_rptr =
91422eb7cb5Sgd 		    &wscons.wc_polledio;
9157c478bd9Sstevel@tonic-gate 
916fea9cb91Slq 		mp->b_datap->db_type = M_IOCACK;
9177c478bd9Sstevel@tonic-gate 
9187c478bd9Sstevel@tonic-gate 		qreply(q, mp);
9197c478bd9Sstevel@tonic-gate 		break;
9207c478bd9Sstevel@tonic-gate 
921fea9cb91Slq 	case CONS_GETTERM:
922fea9cb91Slq 		if ((error = wc_getterm(mp)) != 0)
923fea9cb91Slq 			miocnak(q, mp, 0, error);
924fea9cb91Slq 		else
925fea9cb91Slq 			miocack(q, mp, 0, 0);
926fea9cb91Slq 		return;
927fea9cb91Slq 
9287c478bd9Sstevel@tonic-gate 	case WC_OPEN_FB:
9297c478bd9Sstevel@tonic-gate 		/*
9307c478bd9Sstevel@tonic-gate 		 * Start out pessimistic, so that we can just jump to
9317c478bd9Sstevel@tonic-gate 		 * the reply to bail out.
9327c478bd9Sstevel@tonic-gate 		 */
9337c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_IOCNAK;
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 		/*
9367c478bd9Sstevel@tonic-gate 		 * First test:  really, this should be done only from
9377c478bd9Sstevel@tonic-gate 		 * inside the kernel.  Unfortunately, that information
9387c478bd9Sstevel@tonic-gate 		 * doesn't seem to be available in a streams ioctl,
9397c478bd9Sstevel@tonic-gate 		 * so restrict it to root only.  (Perhaps we could check
9407c478bd9Sstevel@tonic-gate 		 * for ioc_cr == kcred.)
9417c478bd9Sstevel@tonic-gate 		 */
9427c478bd9Sstevel@tonic-gate 		if ((iocp->ioc_error = secpolicy_console(iocp->ioc_cr)) != 0)
9437c478bd9Sstevel@tonic-gate 			goto open_fail;
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 		/*
9467c478bd9Sstevel@tonic-gate 		 * Some miscellaneous checks...
9477c478bd9Sstevel@tonic-gate 		 */
9487c478bd9Sstevel@tonic-gate 		iocp->ioc_error = EINVAL;
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 		/*
9517c478bd9Sstevel@tonic-gate 		 * If we don't have exactly one continuation block, fail.
9527c478bd9Sstevel@tonic-gate 		 */
953aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (mp->b_cont == NULL ||
954aecfc01dSrui zang - Sun Microsystems - Beijing China 		    mp->b_cont->b_cont != NULL)
9557c478bd9Sstevel@tonic-gate 			goto open_fail;
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 		/*
9587c478bd9Sstevel@tonic-gate 		 * If there's no null terminator in the string, fail.
9597c478bd9Sstevel@tonic-gate 		 */
960aecfc01dSrui zang - Sun Microsystems - Beijing China 		/* LINTED E_PTRDIFF_OVERFLOW */
961aecfc01dSrui zang - Sun Microsystems - Beijing China 		len = mp->b_cont->b_wptr - mp->b_cont->b_rptr;
9627c478bd9Sstevel@tonic-gate 		if (memchr(mp->b_cont->b_rptr, 0, len) == NULL)
9637c478bd9Sstevel@tonic-gate 			goto open_fail;
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 		/*
9667c478bd9Sstevel@tonic-gate 		 * NOTE:  should eventually get default
9677c478bd9Sstevel@tonic-gate 		 * dimensions from a property, e.g. screen-#rows.
9687c478bd9Sstevel@tonic-gate 		 */
969aecfc01dSrui zang - Sun Microsystems - Beijing China 		iocp->ioc_error = tem_info_init((char *)mp->b_cont->b_rptr,
970aecfc01dSrui zang - Sun Microsystems - Beijing China 		    iocp->ioc_cr);
9717c478bd9Sstevel@tonic-gate 		/*
9727c478bd9Sstevel@tonic-gate 		 * Of course, if the terminal emulator initialization
9737c478bd9Sstevel@tonic-gate 		 * failed, fail.
9747c478bd9Sstevel@tonic-gate 		 */
9757c478bd9Sstevel@tonic-gate 		if (iocp->ioc_error != 0)
9767c478bd9Sstevel@tonic-gate 			goto open_fail;
9777c478bd9Sstevel@tonic-gate 
978aecfc01dSrui zang - Sun Microsystems - Beijing China #ifdef	_HAVE_TEM_FIRMWARE
979aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (prom_stdout_is_framebuffer()) {
980aecfc01dSrui zang - Sun Microsystems - Beijing China 			/*
981aecfc01dSrui zang - Sun Microsystems - Beijing China 			 * Drivers in the console stream may emit additional
982aecfc01dSrui zang - Sun Microsystems - Beijing China 			 * messages before we are ready. This causes text
983aecfc01dSrui zang - Sun Microsystems - Beijing China 			 * overwrite on the screen. So we set the redirection
984aecfc01dSrui zang - Sun Microsystems - Beijing China 			 * here. It is safe because the ioctl in consconfig_dacf
985aecfc01dSrui zang - Sun Microsystems - Beijing China 			 * will succeed and consmode will be set to CONS_KFB.
986aecfc01dSrui zang - Sun Microsystems - Beijing China 			 */
987aecfc01dSrui zang - Sun Microsystems - Beijing China 			prom_set_stdout_redirect(wc_cons_wrtvec,
988aecfc01dSrui zang - Sun Microsystems - Beijing China 			    (promif_redir_arg_t)NULL);
989fea9cb91Slq 
990aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
991aecfc01dSrui zang - Sun Microsystems - Beijing China #endif	/* _HAVE_TEM_FIRMWARE */
992aecfc01dSrui zang - Sun Microsystems - Beijing China 
993aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_register_modechg_cb(wc_modechg_cb,
994aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (tem_modechg_cb_arg_t)&wscons);
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 		/*
9977c478bd9Sstevel@tonic-gate 		 * ... and succeed.
9987c478bd9Sstevel@tonic-gate 		 */
9997c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_IOCACK;
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate open_fail:
10027c478bd9Sstevel@tonic-gate 		qreply(q, mp);
10037c478bd9Sstevel@tonic-gate 		break;
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	case WC_CLOSE_FB:
10067c478bd9Sstevel@tonic-gate 		/*
10077c478bd9Sstevel@tonic-gate 		 * There's nothing that can call this, so it's not
10087c478bd9Sstevel@tonic-gate 		 * really implemented.
10097c478bd9Sstevel@tonic-gate 		 */
10107c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_IOCNAK;
10117c478bd9Sstevel@tonic-gate 		/*
10127c478bd9Sstevel@tonic-gate 		 * However, if it were implemented, it would clearly
10137c478bd9Sstevel@tonic-gate 		 * be root-only.
10147c478bd9Sstevel@tonic-gate 		 */
10157c478bd9Sstevel@tonic-gate 		if ((iocp->ioc_error = secpolicy_console(iocp->ioc_cr)) != 0)
10167c478bd9Sstevel@tonic-gate 			goto close_fail;
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate 		iocp->ioc_error = EINVAL;
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate close_fail:
10217c478bd9Sstevel@tonic-gate 		qreply(q, mp);
10227c478bd9Sstevel@tonic-gate 		break;
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 	default:
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 		/*
10277c478bd9Sstevel@tonic-gate 		 * The only way in which "ttycommon_ioctl" can fail is
10287c478bd9Sstevel@tonic-gate 		 * if the "ioctl" requires a response containing data
10297c478bd9Sstevel@tonic-gate 		 * to be returned to the user, and no mblk could be
10307c478bd9Sstevel@tonic-gate 		 * allocated for the data.  No such "ioctl" alters our
10317c478bd9Sstevel@tonic-gate 		 * state.  Thus, we always go ahead and do any
10327c478bd9Sstevel@tonic-gate 		 * state-changes the "ioctl" calls for.  If we couldn't
10337c478bd9Sstevel@tonic-gate 		 * allocate the data, "ttycommon_ioctl" has stashed the
10347c478bd9Sstevel@tonic-gate 		 * "ioctl" away safely, so we just call "qbufcall" to
10357c478bd9Sstevel@tonic-gate 		 * request that we be called back when we stand a
10367c478bd9Sstevel@tonic-gate 		 * better chance of allocating the data.
10377c478bd9Sstevel@tonic-gate 		 */
1038aecfc01dSrui zang - Sun Microsystems - Beijing China 		datasize = ttycommon_ioctl(&pvc->vc_ttycommon, q, mp, &error);
10397c478bd9Sstevel@tonic-gate 		if (datasize != 0) {
1040aecfc01dSrui zang - Sun Microsystems - Beijing China 			if (pvc->vc_bufcallid != 0)
1041aecfc01dSrui zang - Sun Microsystems - Beijing China 				qunbufcall(q, pvc->vc_bufcallid);
1042aecfc01dSrui zang - Sun Microsystems - Beijing China 			pvc->vc_bufcallid = qbufcall(q, datasize, BPRI_HI,
1043aecfc01dSrui zang - Sun Microsystems - Beijing China 			    wcreioctl, pvc);
10447c478bd9Sstevel@tonic-gate 			return;
10457c478bd9Sstevel@tonic-gate 		}
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 		if (error < 0) {
10487c478bd9Sstevel@tonic-gate 			if (iocp->ioc_cmd == TCSBRK)
10497c478bd9Sstevel@tonic-gate 				error = 0;
10507c478bd9Sstevel@tonic-gate 			else
10517c478bd9Sstevel@tonic-gate 				error = EINVAL;
10527c478bd9Sstevel@tonic-gate 		}
10537c478bd9Sstevel@tonic-gate 		if (error != 0) {
10547c478bd9Sstevel@tonic-gate 			iocp->ioc_error = error;
10557c478bd9Sstevel@tonic-gate 			mp->b_datap->db_type = M_IOCNAK;
10567c478bd9Sstevel@tonic-gate 		}
10577c478bd9Sstevel@tonic-gate 		qreply(q, mp);
10587c478bd9Sstevel@tonic-gate 		break;
10597c478bd9Sstevel@tonic-gate 	}
10607c478bd9Sstevel@tonic-gate }
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate /*
10637c478bd9Sstevel@tonic-gate  * This function gets the polled I/O structures from the lower
10647c478bd9Sstevel@tonic-gate  * keyboard driver.  If any initialization or resource allocation
10657c478bd9Sstevel@tonic-gate  * needs to be done by the lower driver, it will be done when
10667c478bd9Sstevel@tonic-gate  * the lower driver services this message.
10677c478bd9Sstevel@tonic-gate  */
10687c478bd9Sstevel@tonic-gate static void
wc_open_kb_polledio(struct wscons_state * wscons,queue_t * q,mblk_t * mp)1069aecfc01dSrui zang - Sun Microsystems - Beijing China wc_open_kb_polledio(struct wscons_state *wscons, queue_t *q, mblk_t *mp)
10707c478bd9Sstevel@tonic-gate {
10717c478bd9Sstevel@tonic-gate 	mblk_t *mp2;
10727c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L1, PRINT_MASK_ALL,
107522eb7cb5Sgd 	    ("wc_open_kb_polledio: sending CONSOPENPOLLEDIO\n"));
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate 	mp2 = mkiocb(CONSOPENPOLLEDIO);
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	if (mp2 == NULL) {
10807c478bd9Sstevel@tonic-gate 		/*
10817c478bd9Sstevel@tonic-gate 		 * If we can't get an mblk, then wait for it.
10827c478bd9Sstevel@tonic-gate 		 */
10837c478bd9Sstevel@tonic-gate 		goto nomem;
10847c478bd9Sstevel@tonic-gate 	}
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	mp2->b_cont = allocb(sizeof (struct cons_polledio *), BPRI_HI);
10877c478bd9Sstevel@tonic-gate 
10887c478bd9Sstevel@tonic-gate 	if (mp2->b_cont == NULL) {
10897c478bd9Sstevel@tonic-gate 		/*
10907c478bd9Sstevel@tonic-gate 		 * If we can't get an mblk, then wait for it, and release
10917c478bd9Sstevel@tonic-gate 		 * the mblk that we have already allocated.
10927c478bd9Sstevel@tonic-gate 		 */
10937c478bd9Sstevel@tonic-gate 		freemsg(mp2);
10947c478bd9Sstevel@tonic-gate 		goto nomem;
10957c478bd9Sstevel@tonic-gate 	}
10967c478bd9Sstevel@tonic-gate 
1097aecfc01dSrui zang - Sun Microsystems - Beijing China 	iocp = (struct iocblk *)(void *)mp2->b_rptr;
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate 	iocp->ioc_count = sizeof (struct cons_polledio *);
11007c478bd9Sstevel@tonic-gate 	mp2->b_cont->b_wptr = mp2->b_cont->b_rptr +
110122eb7cb5Sgd 	    sizeof (struct cons_polledio *);
11027c478bd9Sstevel@tonic-gate 
1103aecfc01dSrui zang - Sun Microsystems - Beijing China 	wscons->wc_pending_wq = q;
11047c478bd9Sstevel@tonic-gate 	wscons->wc_pending_link = mp;
11057c478bd9Sstevel@tonic-gate 	wscons->wc_kb_getpolledio_id = iocp->ioc_id;
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	putnext(wscons->wc_kbdqueue, mp2);
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 	return;
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate nomem:
1112aecfc01dSrui zang - Sun Microsystems - Beijing China 	iocp = (struct iocblk *)(void *)mp->b_rptr;
11137c478bd9Sstevel@tonic-gate 	iocp->ioc_error = ENOMEM;
11147c478bd9Sstevel@tonic-gate 	mp->b_datap->db_type = M_IOCNAK;
11157c478bd9Sstevel@tonic-gate 	qreply(q, mp);
11167c478bd9Sstevel@tonic-gate }
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate /*
11197c478bd9Sstevel@tonic-gate  * This function releases the polled I/O structures from the lower
11207c478bd9Sstevel@tonic-gate  * keyboard driver.  If any de-initialization needs to be done, or
11217c478bd9Sstevel@tonic-gate  * any resources need to be released, it will be done when the lower
11227c478bd9Sstevel@tonic-gate  * driver services this message.
11237c478bd9Sstevel@tonic-gate  */
11247c478bd9Sstevel@tonic-gate static void
wc_close_kb_polledio(struct wscons_state * wscons,queue_t * q,mblk_t * mp)1125aecfc01dSrui zang - Sun Microsystems - Beijing China wc_close_kb_polledio(struct wscons_state *wscons, queue_t *q, mblk_t *mp)
11267c478bd9Sstevel@tonic-gate {
11277c478bd9Sstevel@tonic-gate 	mblk_t *mp2;
11287c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L1, PRINT_MASK_ALL,
113122eb7cb5Sgd 	    ("wc_close_kb_polledio: sending CONSCLOSEPOLLEDIO\n"));
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate 	mp2 = mkiocb(CONSCLOSEPOLLEDIO);
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 	if (mp2 == NULL) {
11367c478bd9Sstevel@tonic-gate 		/*
11377c478bd9Sstevel@tonic-gate 		 * If we can't get an mblk, then wait for it.
11387c478bd9Sstevel@tonic-gate 		 */
11397c478bd9Sstevel@tonic-gate 		goto nomem;
11407c478bd9Sstevel@tonic-gate 	}
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 	mp2->b_cont = allocb(sizeof (struct cons_polledio *), BPRI_HI);
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate 	if (mp2->b_cont == NULL) {
11457c478bd9Sstevel@tonic-gate 		/*
11467c478bd9Sstevel@tonic-gate 		 * If we can't get an mblk, then wait for it, and release
11477c478bd9Sstevel@tonic-gate 		 * the mblk that we have already allocated.
11487c478bd9Sstevel@tonic-gate 		 */
11497c478bd9Sstevel@tonic-gate 		freemsg(mp2);
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 		goto nomem;
11527c478bd9Sstevel@tonic-gate 	}
11537c478bd9Sstevel@tonic-gate 
1154aecfc01dSrui zang - Sun Microsystems - Beijing China 	iocp = (struct iocblk *)(void *)mp2->b_rptr;
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 	iocp->ioc_count = 0;
11577c478bd9Sstevel@tonic-gate 
1158aecfc01dSrui zang - Sun Microsystems - Beijing China 	wscons->wc_pending_wq = q;
11597c478bd9Sstevel@tonic-gate 	wscons->wc_pending_link = mp;
11607c478bd9Sstevel@tonic-gate 	wscons->wc_kb_getpolledio_id = iocp->ioc_id;
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	putnext(wscons->wc_kbdqueue, mp2);
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 	return;
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate nomem:
1167aecfc01dSrui zang - Sun Microsystems - Beijing China 	iocp = (struct iocblk *)(void *)mp->b_rptr;
11687c478bd9Sstevel@tonic-gate 	iocp->ioc_error = ENOMEM;
11697c478bd9Sstevel@tonic-gate 	mp->b_datap->db_type = M_IOCNAK;
11707c478bd9Sstevel@tonic-gate 	qreply(q, mp);
11717c478bd9Sstevel@tonic-gate }
11727c478bd9Sstevel@tonic-gate 
1173fea9cb91Slq #ifdef _HAVE_TEM_FIRMWARE
11747c478bd9Sstevel@tonic-gate /* ARGSUSED */
11757c478bd9Sstevel@tonic-gate static void
wcopoll(void * arg)11767c478bd9Sstevel@tonic-gate wcopoll(void *arg)
11777c478bd9Sstevel@tonic-gate {
1178aecfc01dSrui zang - Sun Microsystems - Beijing China 	vc_state_t *pvc = (vc_state_t *)arg;
11797c478bd9Sstevel@tonic-gate 	queue_t *q;
11807c478bd9Sstevel@tonic-gate 
1181aecfc01dSrui zang - Sun Microsystems - Beijing China 	q = pvc->vc_ttycommon.t_writeq;
1182aecfc01dSrui zang - Sun Microsystems - Beijing China 	pvc->vc_timeoutid = 0;
1183aecfc01dSrui zang - Sun Microsystems - Beijing China 
1184aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&pvc->vc_state_lock);
1185aecfc01dSrui zang - Sun Microsystems - Beijing China 
11867c478bd9Sstevel@tonic-gate 	/* See if we can continue output */
1187aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((pvc->vc_flags & WCS_BUSY) && pvc->vc_pendc != -1) {
1188aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (prom_mayput((char)pvc->vc_pendc) == 0) {
1189aecfc01dSrui zang - Sun Microsystems - Beijing China 			pvc->vc_pendc = -1;
1190aecfc01dSrui zang - Sun Microsystems - Beijing China 			pvc->vc_flags &= ~WCS_BUSY;
1191aecfc01dSrui zang - Sun Microsystems - Beijing China 			if (!(pvc->vc_flags&(WCS_DELAY|WCS_STOPPED)))
1192d4a54bf7SToomas Soome 				qenable(q);
11937c478bd9Sstevel@tonic-gate 		} else
1194aecfc01dSrui zang - Sun Microsystems - Beijing China 			pvc->vc_timeoutid = qtimeout(q, wcopoll, pvc, 1);
11957c478bd9Sstevel@tonic-gate 	}
1196aecfc01dSrui zang - Sun Microsystems - Beijing China 
1197aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&pvc->vc_state_lock);
11987c478bd9Sstevel@tonic-gate }
1199fea9cb91Slq #endif	/* _HAVE_TEM_FIRMWARE */
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate /*
12027c478bd9Sstevel@tonic-gate  * Restart output on the console after a timeout.
12037c478bd9Sstevel@tonic-gate  */
12047c478bd9Sstevel@tonic-gate /* ARGSUSED */
12057c478bd9Sstevel@tonic-gate static void
wcrstrt(void * arg)12067c478bd9Sstevel@tonic-gate wcrstrt(void *arg)
12077c478bd9Sstevel@tonic-gate {
1208aecfc01dSrui zang - Sun Microsystems - Beijing China 	vc_state_t *pvc = (vc_state_t *)arg;
1209aecfc01dSrui zang - Sun Microsystems - Beijing China 
1210aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(pvc->vc_ttycommon.t_writeq != NULL);
1211aecfc01dSrui zang - Sun Microsystems - Beijing China 
1212aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&pvc->vc_state_lock);
1213aecfc01dSrui zang - Sun Microsystems - Beijing China 	pvc->vc_flags &= ~WCS_DELAY;
1214aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&pvc->vc_state_lock);
1215aecfc01dSrui zang - Sun Microsystems - Beijing China 
1216d4a54bf7SToomas Soome 	qenable(pvc->vc_ttycommon.t_writeq);
1217aecfc01dSrui zang - Sun Microsystems - Beijing China }
1218aecfc01dSrui zang - Sun Microsystems - Beijing China 
1219aecfc01dSrui zang - Sun Microsystems - Beijing China /*
1220aecfc01dSrui zang - Sun Microsystems - Beijing China  * get screen terminal for current output
1221aecfc01dSrui zang - Sun Microsystems - Beijing China  */
1222aecfc01dSrui zang - Sun Microsystems - Beijing China static tem_vt_state_t
wc_get_screen_tem(vc_state_t * pvc)1223aecfc01dSrui zang - Sun Microsystems - Beijing China wc_get_screen_tem(vc_state_t *pvc)
1224aecfc01dSrui zang - Sun Microsystems - Beijing China {
1225aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!tem_initialized(pvc->vc_tem) ||
1226aecfc01dSrui zang - Sun Microsystems - Beijing China 	    tem_get_fbmode(pvc->vc_tem) != KD_TEXT)
1227aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (NULL);
1228aecfc01dSrui zang - Sun Microsystems - Beijing China 
1229aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (pvc->vc_tem);
12307c478bd9Sstevel@tonic-gate }
12317c478bd9Sstevel@tonic-gate 
12327c478bd9Sstevel@tonic-gate /*
12337c478bd9Sstevel@tonic-gate  * Put procedure for lower read queue.
12347c478bd9Sstevel@tonic-gate  * Pass everything up to queue above "upper half".
12357c478bd9Sstevel@tonic-gate  */
12367c478bd9Sstevel@tonic-gate static int
wclrput(queue_t * q,mblk_t * mp)12377c478bd9Sstevel@tonic-gate wclrput(queue_t *q, mblk_t *mp)
12387c478bd9Sstevel@tonic-gate {
1239aecfc01dSrui zang - Sun Microsystems - Beijing China 	vc_state_t *pvc;
12407c478bd9Sstevel@tonic-gate 	queue_t *upq;
12417c478bd9Sstevel@tonic-gate 	struct iocblk *iocp;
12427c478bd9Sstevel@tonic-gate 
1243aecfc01dSrui zang - Sun Microsystems - Beijing China 	pvc = vt_minor2vc(VT_ACTIVE);
1244aecfc01dSrui zang - Sun Microsystems - Beijing China 
12457c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L1, PRINT_MASK_ALL,
124622eb7cb5Sgd 	    ("wclrput: wclrput type = 0x%x\n", mp->b_datap->db_type));
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 	case M_FLUSH:
12517c478bd9Sstevel@tonic-gate 		if (*mp->b_rptr == FLUSHW || *mp->b_rptr == FLUSHRW) {
12527c478bd9Sstevel@tonic-gate 			/*
12537c478bd9Sstevel@tonic-gate 			 * Flush our write queue.
12547c478bd9Sstevel@tonic-gate 			 */
12557c478bd9Sstevel@tonic-gate 			/* XXX doesn't flush M_DELAY */
12567c478bd9Sstevel@tonic-gate 			flushq(WR(q), FLUSHDATA);
12577c478bd9Sstevel@tonic-gate 			*mp->b_rptr = FLUSHR;	/* it has been flushed */
12587c478bd9Sstevel@tonic-gate 		}
12597c478bd9Sstevel@tonic-gate 		if (*mp->b_rptr == FLUSHR || *mp->b_rptr == FLUSHRW) {
12607c478bd9Sstevel@tonic-gate 			flushq(q, FLUSHDATA);
12617c478bd9Sstevel@tonic-gate 			*mp->b_rptr = FLUSHW;	/* it has been flushed */
12627c478bd9Sstevel@tonic-gate 			qreply(q, mp);	/* give the read queues a crack at it */
12637c478bd9Sstevel@tonic-gate 		} else
12647c478bd9Sstevel@tonic-gate 			freemsg(mp);
12657c478bd9Sstevel@tonic-gate 		break;
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate 	case M_DATA:
1268aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (consmode == CONS_KFB && vt_check_hotkeys(mp)) {
1269aecfc01dSrui zang - Sun Microsystems - Beijing China 			freemsg(mp);
1270aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
1271aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
1272aecfc01dSrui zang - Sun Microsystems - Beijing China 
1273aecfc01dSrui zang - Sun Microsystems - Beijing China 		if ((upq = pvc->vc_ttycommon.t_readq) != NULL) {
12747c478bd9Sstevel@tonic-gate 			if (!canput(upq->q_next)) {
1275aecfc01dSrui zang - Sun Microsystems - Beijing China 				ttycommon_qfull(&pvc->vc_ttycommon, upq);
1276d4a54bf7SToomas Soome 				qenable(WR(upq));
12777c478bd9Sstevel@tonic-gate 				freemsg(mp);
1278aecfc01dSrui zang - Sun Microsystems - Beijing China 			} else {
12797c478bd9Sstevel@tonic-gate 				putnext(upq, mp);
1280aecfc01dSrui zang - Sun Microsystems - Beijing China 			}
12817c478bd9Sstevel@tonic-gate 		} else
12827c478bd9Sstevel@tonic-gate 			freemsg(mp);
12837c478bd9Sstevel@tonic-gate 		break;
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 	case M_IOCACK:
12867c478bd9Sstevel@tonic-gate 	case M_IOCNAK:
1287aecfc01dSrui zang - Sun Microsystems - Beijing China 		iocp = (struct iocblk *)(void *)mp->b_rptr;
12887c478bd9Sstevel@tonic-gate 		if (wscons.wc_pending_link != NULL &&
12897c478bd9Sstevel@tonic-gate 		    iocp->ioc_id == wscons.wc_kb_getpolledio_id) {
12907c478bd9Sstevel@tonic-gate 			switch (mp->b_datap->db_type) {
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 			case M_IOCACK:
12937c478bd9Sstevel@tonic-gate 				switch (iocp->ioc_cmd) {
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 				case CONSOPENPOLLEDIO:
12967c478bd9Sstevel@tonic-gate 					DPRINTF(PRINT_L1, PRINT_MASK_ALL,
129722eb7cb5Sgd 					    ("wclrput: "
129822eb7cb5Sgd 					    "ACK CONSOPENPOLLEDIO\n"));
12997c478bd9Sstevel@tonic-gate 					wscons.wc_kb_polledio =
1300aecfc01dSrui zang - Sun Microsystems - Beijing China 					    *(struct cons_polledio **)
1301aecfc01dSrui zang - Sun Microsystems - Beijing China 					    (void *)mp->b_cont->b_rptr;
1302fea9cb91Slq 					wscons.wc_polledio.
1303fea9cb91Slq 					    cons_polledio_getchar =
130422eb7cb5Sgd 					    wc_polled_getchar;
1305fea9cb91Slq 					wscons.wc_polledio.
1306fea9cb91Slq 					    cons_polledio_ischar =
130722eb7cb5Sgd 					    wc_polled_ischar;
13087c478bd9Sstevel@tonic-gate 					break;
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 				case CONSCLOSEPOLLEDIO:
13117c478bd9Sstevel@tonic-gate 					DPRINTF(PRINT_L1, PRINT_MASK_ALL,
131222eb7cb5Sgd 					    ("wclrput: "
131322eb7cb5Sgd 					    "ACK CONSCLOSEPOLLEDIO\n"));
13147c478bd9Sstevel@tonic-gate 					wscons.wc_kb_polledio = NULL;
13157c478bd9Sstevel@tonic-gate 					wscons.wc_kbdqueue = NULL;
1316fea9cb91Slq 					wscons.wc_polledio.
1317fea9cb91Slq 					    cons_polledio_getchar = NULL;
1318fea9cb91Slq 					wscons.wc_polledio.
1319fea9cb91Slq 					    cons_polledio_ischar = NULL;
13207c478bd9Sstevel@tonic-gate 					break;
13217c478bd9Sstevel@tonic-gate 				default:
13227c478bd9Sstevel@tonic-gate 					DPRINTF(PRINT_L1, PRINT_MASK_ALL,
1323aecfc01dSrui zang - Sun Microsystems - Beijing China 					    ("wclrput: "
1324aecfc01dSrui zang - Sun Microsystems - Beijing China 					    "ACK UNKNOWN\n"));
13257c478bd9Sstevel@tonic-gate 				}
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 				break;
13287c478bd9Sstevel@tonic-gate 			case M_IOCNAK:
13297c478bd9Sstevel@tonic-gate 				/*
13307c478bd9Sstevel@tonic-gate 				 * Keyboard may or may not support polled I/O.
13317c478bd9Sstevel@tonic-gate 				 * This ioctl may have been rejected because
13327c478bd9Sstevel@tonic-gate 				 * we only have the wc->conskbd chain built,
13337c478bd9Sstevel@tonic-gate 				 * and the keyboard driver has not been linked
13347c478bd9Sstevel@tonic-gate 				 * underneath conskbd yet.
13357c478bd9Sstevel@tonic-gate 				 */
13367c478bd9Sstevel@tonic-gate 				DPRINTF(PRINT_L1, PRINT_MASK_ALL,
133722eb7cb5Sgd 				    ("wclrput: NAK\n"));
13387c478bd9Sstevel@tonic-gate 
13397c478bd9Sstevel@tonic-gate 				switch (iocp->ioc_cmd) {
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 				case CONSCLOSEPOLLEDIO:
13427c478bd9Sstevel@tonic-gate 					wscons.wc_kb_polledio = NULL;
13437c478bd9Sstevel@tonic-gate 					wscons.wc_kbdqueue = NULL;
1344fea9cb91Slq 					wscons.wc_polledio.
1345fea9cb91Slq 					    cons_polledio_getchar = NULL;
1346fea9cb91Slq 					wscons.wc_polledio.
1347fea9cb91Slq 					    cons_polledio_ischar = NULL;
13487c478bd9Sstevel@tonic-gate 					break;
13497c478bd9Sstevel@tonic-gate 				}
13507c478bd9Sstevel@tonic-gate 				break;
13517c478bd9Sstevel@tonic-gate 			}
13527c478bd9Sstevel@tonic-gate 
13537c478bd9Sstevel@tonic-gate 			/*
13547c478bd9Sstevel@tonic-gate 			 * Discard the response, replace it with the
13557c478bd9Sstevel@tonic-gate 			 * pending response to the I_PLINK, then let it
13567c478bd9Sstevel@tonic-gate 			 * flow upward.
13577c478bd9Sstevel@tonic-gate 			 */
13587c478bd9Sstevel@tonic-gate 			freemsg(mp);
13597c478bd9Sstevel@tonic-gate 			mp = wscons.wc_pending_link;
13607c478bd9Sstevel@tonic-gate 			wscons.wc_pending_link = NULL;
13617c478bd9Sstevel@tonic-gate 			wscons.wc_kb_getpolledio_id = 0;
13627c478bd9Sstevel@tonic-gate 		}
13637c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
13647c478bd9Sstevel@tonic-gate 
13657c478bd9Sstevel@tonic-gate 	default:	/* inc M_ERROR, M_HANGUP, M_IOCACK, M_IOCNAK, ... */
1366aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (wscons.wc_pending_wq != NULL) {
1367aecfc01dSrui zang - Sun Microsystems - Beijing China 			qreply(wscons.wc_pending_wq, mp);
1368aecfc01dSrui zang - Sun Microsystems - Beijing China 			wscons.wc_pending_wq = NULL;
1369aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
1370aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
1371aecfc01dSrui zang - Sun Microsystems - Beijing China 
1372aecfc01dSrui zang - Sun Microsystems - Beijing China 		if ((upq = pvc->vc_ttycommon.t_readq) != NULL) {
13737c478bd9Sstevel@tonic-gate 			putnext(upq, mp);
13747c478bd9Sstevel@tonic-gate 		} else {
1375aecfc01dSrui zang - Sun Microsystems - Beijing China 			DPRINTF(PRINT_L1, PRINT_MASK_ALL,
1376aecfc01dSrui zang - Sun Microsystems - Beijing China 			    ("wclrput: Message DISCARDED\n"));
13777c478bd9Sstevel@tonic-gate 			freemsg(mp);
13787c478bd9Sstevel@tonic-gate 		}
13797c478bd9Sstevel@tonic-gate 		break;
13807c478bd9Sstevel@tonic-gate 	}
13817c478bd9Sstevel@tonic-gate 
13827c478bd9Sstevel@tonic-gate 	return (0);
13837c478bd9Sstevel@tonic-gate }
13847c478bd9Sstevel@tonic-gate 
1385aecfc01dSrui zang - Sun Microsystems - Beijing China #ifdef _HAVE_TEM_FIRMWARE
1386aecfc01dSrui zang - Sun Microsystems - Beijing China /*
1387aecfc01dSrui zang - Sun Microsystems - Beijing China  *  This routine exists so that prom_write() can redirect writes
1388aecfc01dSrui zang - Sun Microsystems - Beijing China  *  to the framebuffer through the kernel terminal emulator, if
1389aecfc01dSrui zang - Sun Microsystems - Beijing China  *  that configuration is selected during consconfig.
1390aecfc01dSrui zang - Sun Microsystems - Beijing China  *  When the kernel terminal emulator is enabled, consconfig_dacf
1391aecfc01dSrui zang - Sun Microsystems - Beijing China  *  sets up the PROM output redirect vector to enter this function.
1392aecfc01dSrui zang - Sun Microsystems - Beijing China  *  During panic the console will already be powered up as part of
1393aecfc01dSrui zang - Sun Microsystems - Beijing China  *  calling into the prom_*() layer.
1394aecfc01dSrui zang - Sun Microsystems - Beijing China  */
1395aecfc01dSrui zang - Sun Microsystems - Beijing China /* ARGSUSED */
1396aecfc01dSrui zang - Sun Microsystems - Beijing China ssize_t
wc_cons_wrtvec(promif_redir_arg_t arg,uchar_t * s,size_t n)1397aecfc01dSrui zang - Sun Microsystems - Beijing China wc_cons_wrtvec(promif_redir_arg_t arg, uchar_t *s, size_t n)
1398aecfc01dSrui zang - Sun Microsystems - Beijing China {
1399aecfc01dSrui zang - Sun Microsystems - Beijing China 	vc_state_t *pvc;
1400aecfc01dSrui zang - Sun Microsystems - Beijing China 
1401aecfc01dSrui zang - Sun Microsystems - Beijing China 	pvc = vt_minor2vc(VT_ACTIVE);
1402aecfc01dSrui zang - Sun Microsystems - Beijing China 
1403aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pvc->vc_tem == NULL)
1404aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (0);
1405aecfc01dSrui zang - Sun Microsystems - Beijing China 
1406aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(consmode == CONS_KFB);
1407aecfc01dSrui zang - Sun Microsystems - Beijing China 
1408aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (panicstr)
1409aecfc01dSrui zang - Sun Microsystems - Beijing China 		polled_io_cons_write(s, n);
1410aecfc01dSrui zang - Sun Microsystems - Beijing China 	else
1411aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) tem_write(pvc->vc_tem, s, n, kcred);
1412aecfc01dSrui zang - Sun Microsystems - Beijing China 
1413aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (n);
1414aecfc01dSrui zang - Sun Microsystems - Beijing China }
1415aecfc01dSrui zang - Sun Microsystems - Beijing China #endif /* _HAVE_TEM_FIRMWARE */
1416aecfc01dSrui zang - Sun Microsystems - Beijing China 
14177c478bd9Sstevel@tonic-gate /*
1418fea9cb91Slq  * These are for systems without OBP, and for devices that cannot be
1419fea9cb91Slq  * shared between Solaris and the OBP.
14207c478bd9Sstevel@tonic-gate  */
14217c478bd9Sstevel@tonic-gate static void
wc_polled_putchar(cons_polledio_arg_t arg,unsigned char c)1422281f0747Slt wc_polled_putchar(cons_polledio_arg_t arg, unsigned char c)
14237c478bd9Sstevel@tonic-gate {
1424aecfc01dSrui zang - Sun Microsystems - Beijing China 	vc_state_t *pvc;
1425aecfc01dSrui zang - Sun Microsystems - Beijing China 
1426aecfc01dSrui zang - Sun Microsystems - Beijing China 	pvc = vt_minor2vc(VT_ACTIVE);
1427aecfc01dSrui zang - Sun Microsystems - Beijing China 
14287c478bd9Sstevel@tonic-gate 	if (c == '\n')
1429fea9cb91Slq 		wc_polled_putchar(arg, '\r');
14307c478bd9Sstevel@tonic-gate 
1431aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pvc->vc_tem == NULL) {
14327c478bd9Sstevel@tonic-gate 		/*
14337c478bd9Sstevel@tonic-gate 		 * We have no terminal emulator configured.  We have no
14347c478bd9Sstevel@tonic-gate 		 * recourse but to drop the output on the floor.
14357c478bd9Sstevel@tonic-gate 		 */
14367c478bd9Sstevel@tonic-gate 		return;
14377c478bd9Sstevel@tonic-gate 	}
14387c478bd9Sstevel@tonic-gate 
1439aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_safe_polled_write(pvc->vc_tem, &c, 1);
14407c478bd9Sstevel@tonic-gate }
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate /*
14437c478bd9Sstevel@tonic-gate  * These are for systems without OBP, and for devices that cannot be
14447c478bd9Sstevel@tonic-gate  * shared between Solaris and the OBP.
14457c478bd9Sstevel@tonic-gate  */
14467c478bd9Sstevel@tonic-gate static int
wc_polled_getchar(cons_polledio_arg_t arg)1447281f0747Slt wc_polled_getchar(cons_polledio_arg_t arg)
14487c478bd9Sstevel@tonic-gate {
1449aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct wscons_state *wscons = (struct wscons_state *)arg;
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	if (wscons->wc_kb_polledio == NULL) {
14527c478bd9Sstevel@tonic-gate 		prom_printf("wscons:  getchar with no keyboard support");
14537c478bd9Sstevel@tonic-gate 		prom_printf("Halted...");
14547c478bd9Sstevel@tonic-gate 		for (;;)
14557c478bd9Sstevel@tonic-gate 			/* HANG FOREVER */;
14567c478bd9Sstevel@tonic-gate 	}
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 	return (wscons->wc_kb_polledio->cons_polledio_getchar(
1459fea9cb91Slq 	    wscons->wc_kb_polledio->cons_polledio_argument));
14607c478bd9Sstevel@tonic-gate }
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate static boolean_t
wc_polled_ischar(cons_polledio_arg_t arg)1463281f0747Slt wc_polled_ischar(cons_polledio_arg_t arg)
14647c478bd9Sstevel@tonic-gate {
1465aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct wscons_state *wscons = (struct wscons_state *)arg;
14667c478bd9Sstevel@tonic-gate 
14677c478bd9Sstevel@tonic-gate 	if (wscons->wc_kb_polledio == NULL)
14687c478bd9Sstevel@tonic-gate 		return (B_FALSE);
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate 	return (wscons->wc_kb_polledio->cons_polledio_ischar(
1471fea9cb91Slq 	    wscons->wc_kb_polledio->cons_polledio_argument));
14727c478bd9Sstevel@tonic-gate }
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate static void
wc_polled_enter(cons_polledio_arg_t arg)1475281f0747Slt wc_polled_enter(cons_polledio_arg_t arg)
14767c478bd9Sstevel@tonic-gate {
1477aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct wscons_state *wscons = (struct wscons_state *)arg;
14787c478bd9Sstevel@tonic-gate 
14797c478bd9Sstevel@tonic-gate 	if (wscons->wc_kb_polledio == NULL)
14807c478bd9Sstevel@tonic-gate 		return;
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate 	if (wscons->wc_kb_polledio->cons_polledio_enter != NULL) {
14837c478bd9Sstevel@tonic-gate 		wscons->wc_kb_polledio->cons_polledio_enter(
1484fea9cb91Slq 		    wscons->wc_kb_polledio->cons_polledio_argument);
14857c478bd9Sstevel@tonic-gate 	}
14867c478bd9Sstevel@tonic-gate }
14877c478bd9Sstevel@tonic-gate 
14887c478bd9Sstevel@tonic-gate static void
wc_polled_exit(cons_polledio_arg_t arg)1489281f0747Slt wc_polled_exit(cons_polledio_arg_t arg)
14907c478bd9Sstevel@tonic-gate {
1491aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct wscons_state *wscons = (struct wscons_state *)arg;
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate 	if (wscons->wc_kb_polledio == NULL)
14947c478bd9Sstevel@tonic-gate 		return;
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate 	if (wscons->wc_kb_polledio->cons_polledio_exit != NULL) {
14977c478bd9Sstevel@tonic-gate 		wscons->wc_kb_polledio->cons_polledio_exit(
1498fea9cb91Slq 		    wscons->wc_kb_polledio->cons_polledio_argument);
14997c478bd9Sstevel@tonic-gate 	}
15007c478bd9Sstevel@tonic-gate }
15017c478bd9Sstevel@tonic-gate 
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate #ifdef DEBUG
15047c478bd9Sstevel@tonic-gate static void
wc_dprintf(const char * fmt,...)15057c478bd9Sstevel@tonic-gate wc_dprintf(const char *fmt, ...)
15067c478bd9Sstevel@tonic-gate {
15077c478bd9Sstevel@tonic-gate 	char buf[256];
15087c478bd9Sstevel@tonic-gate 	va_list ap;
15097c478bd9Sstevel@tonic-gate 
15107c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
15117c478bd9Sstevel@tonic-gate 	(void) vsprintf(buf, fmt, ap);
15127c478bd9Sstevel@tonic-gate 	va_end(ap);
15137c478bd9Sstevel@tonic-gate 
1514fea9cb91Slq 	cmn_err(CE_WARN, "wc: %s", buf);
15157c478bd9Sstevel@tonic-gate }
15167c478bd9Sstevel@tonic-gate #endif
15177c478bd9Sstevel@tonic-gate 
1518aecfc01dSrui zang - Sun Microsystems - Beijing China /*ARGSUSED*/
1519fea9cb91Slq static void
update_property(vc_state_t * pvc,char * name,ushort_t value)1520aecfc01dSrui zang - Sun Microsystems - Beijing China update_property(vc_state_t *pvc, char *name, ushort_t value)
15217c478bd9Sstevel@tonic-gate {
1522fea9cb91Slq 	char data[8];
15237c478bd9Sstevel@tonic-gate 
1524fea9cb91Slq 	(void) snprintf(data, sizeof (data), "%u", value);
1525aecfc01dSrui zang - Sun Microsystems - Beijing China 
1526aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ddi_prop_update_string(wscons.wc_dev, wc_dip, name, data);
15277c478bd9Sstevel@tonic-gate }
15287c478bd9Sstevel@tonic-gate 
15297c478bd9Sstevel@tonic-gate /*
15307c478bd9Sstevel@tonic-gate  * Gets the number of text rows and columns and the
15317c478bd9Sstevel@tonic-gate  * width and height (in pixels) of the console.
15327c478bd9Sstevel@tonic-gate  */
1533aecfc01dSrui zang - Sun Microsystems - Beijing China void
wc_get_size(vc_state_t * pvc)1534aecfc01dSrui zang - Sun Microsystems - Beijing China wc_get_size(vc_state_t *pvc)
15357c478bd9Sstevel@tonic-gate {
1536aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct winsize *t = &pvc->vc_ttycommon.t_size;
1537fea9cb91Slq 	ushort_t r = LOSCREENLINES, c = LOSCREENCOLS, x = 0, y = 0;
15387c478bd9Sstevel@tonic-gate 
1539aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pvc->vc_tem != NULL)
1540aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_get_size(&r, &c, &x, &y);
1541fea9cb91Slq #ifdef _HAVE_TEM_FIRMWARE
1542aecfc01dSrui zang - Sun Microsystems - Beijing China 	else
1543fea9cb91Slq 		console_get_size(&r, &c, &x, &y);
1544fea9cb91Slq #endif /* _HAVE_TEM_FIRMWARE */
1545fea9cb91Slq 
1546aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&pvc->vc_ttycommon.t_excl);
1547aecfc01dSrui zang - Sun Microsystems - Beijing China 	t->ws_col = c;
1548aecfc01dSrui zang - Sun Microsystems - Beijing China 	t->ws_row = r;
1549aecfc01dSrui zang - Sun Microsystems - Beijing China 	t->ws_xpixel = x;
1550aecfc01dSrui zang - Sun Microsystems - Beijing China 	t->ws_ypixel = y;
1551aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&pvc->vc_ttycommon.t_excl);
1552aecfc01dSrui zang - Sun Microsystems - Beijing China 
1553aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pvc->vc_minor != 0)
1554aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1555aecfc01dSrui zang - Sun Microsystems - Beijing China 
1556aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* only for the wscons:0 */
1557aecfc01dSrui zang - Sun Microsystems - Beijing China 	update_property(pvc, "screen-#cols",  c);
1558aecfc01dSrui zang - Sun Microsystems - Beijing China 	update_property(pvc, "screen-#rows",  r);
1559aecfc01dSrui zang - Sun Microsystems - Beijing China 	update_property(pvc, "screen-width",  x);
1560aecfc01dSrui zang - Sun Microsystems - Beijing China 	update_property(pvc, "screen-height", y);
1561fea9cb91Slq }
1562fea9cb91Slq 
1563aecfc01dSrui zang - Sun Microsystems - Beijing China /*ARGSUSED*/
1564fea9cb91Slq static void
wc_modechg_cb(tem_modechg_cb_arg_t arg)1565fea9cb91Slq wc_modechg_cb(tem_modechg_cb_arg_t arg)
1566fea9cb91Slq {
1567aecfc01dSrui zang - Sun Microsystems - Beijing China 	minor_t index;
1568aecfc01dSrui zang - Sun Microsystems - Beijing China 	vc_state_t *pvc;
1569aecfc01dSrui zang - Sun Microsystems - Beijing China 
1570aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&vc_lock);
1571aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (index = 0; index < VC_INSTANCES_COUNT; index++) {
1572aecfc01dSrui zang - Sun Microsystems - Beijing China 		pvc = vt_minor2vc(index);
1573aecfc01dSrui zang - Sun Microsystems - Beijing China 
1574aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_enter(&pvc->vc_state_lock);
1575aecfc01dSrui zang - Sun Microsystems - Beijing China 
1576aecfc01dSrui zang - Sun Microsystems - Beijing China 		if ((pvc->vc_flags & WCS_ISOPEN) &&
1577aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (pvc->vc_flags & WCS_INIT))
1578aecfc01dSrui zang - Sun Microsystems - Beijing China 			wc_get_size(pvc);
1579aecfc01dSrui zang - Sun Microsystems - Beijing China 
1580aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&pvc->vc_state_lock);
1581aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1582aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&vc_lock);
15837c478bd9Sstevel@tonic-gate }
1584