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