Bug Summary

File:dev/wscons/wsdisplay.c
Warning:line 820, column 35
Although the value stored to 'emulops' is used in the enclosing expression, the value is never actually read from 'emulops'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name wsdisplay.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/wscons/wsdisplay.c
1/* $OpenBSD: wsdisplay.c,v 1.143 2021/02/09 14:37:13 jcs Exp $ */
2/* $NetBSD: wsdisplay.c,v 1.82 2005/02/27 00:27:52 perry Exp $ */
3
4/*
5 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Christopher G. Demetriou
18 * for the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/param.h>
35#include <sys/conf.h>
36#include <sys/device.h>
37#include <sys/ioctl.h>
38#include <sys/kernel.h>
39#include <sys/malloc.h>
40#include <sys/syslog.h>
41#include <sys/systm.h>
42#include <sys/tty.h>
43#include <sys/signalvar.h>
44#include <sys/errno.h>
45#include <sys/fcntl.h>
46#include <sys/vnode.h>
47#include <sys/timeout.h>
48#include <sys/poll.h>
49
50#include <dev/wscons/wscons_features.h>
51#include <dev/wscons/wsconsio.h>
52#include <dev/wscons/wsdisplayvar.h>
53#include <dev/wscons/wsksymvar.h>
54#include <dev/wscons/wsksymdef.h>
55#include <dev/wscons/wsemulvar.h>
56#include <dev/wscons/wscons_callbacks.h>
57#include <dev/cons.h>
58
59#include "wsdisplay.h"
60#include "wskbd.h"
61#include "wsmux.h"
62
63#if NWSKBD1 > 0
64#include <dev/wscons/wseventvar.h>
65#include <dev/wscons/wsmuxvar.h>
66#endif
67
68#ifdef DDB1
69#include <ddb/db_output.h>
70#endif
71
72#include "wsmoused.h"
73
74struct wsscreen_internal {
75 const struct wsdisplay_emulops *emulops;
76 void *emulcookie;
77
78 const struct wsscreen_descr *scrdata;
79
80 const struct wsemul_ops *wsemul;
81 void *wsemulcookie;
82};
83
84struct wsscreen {
85 struct wsscreen_internal *scr_dconf;
86
87 struct tty *scr_tty;
88 int scr_hold_screen; /* hold tty output */
89
90 int scr_flags;
91#define SCR_OPEN1 1 /* is it open? */
92#define SCR_WAITACTIVE2 2 /* someone waiting on activation */
93#define SCR_GRAPHICS4 4 /* graphics mode, no text (emulation) output */
94#define SCR_DUMBFB8 8 /* in use as dumb fb (iff SCR_GRAPHICS) */
95
96#ifdef WSDISPLAY_COMPAT_USL1
97 const struct wscons_syncops *scr_syncops;
98 void *scr_synccookie;
99#endif
100
101#ifdef WSDISPLAY_COMPAT_RAWKBD1
102 int scr_rawkbd;
103#endif
104
105 struct wsdisplay_softc *sc;
106
107#ifdef HAVE_WSMOUSED_SUPPORT
108 /* mouse console support via wsmoused(8) */
109 u_int mouse; /* mouse cursor position */
110 u_int cursor; /* selection cursor position (if
111 different from mouse cursor pos) */
112 u_int cpy_start; /* position of the copy start mark*/
113 u_int cpy_end; /* position of the copy end mark */
114 u_int orig_start; /* position of the original sel. start*/
115 u_int orig_end; /* position of the original sel. end */
116
117 u_int mouse_flags; /* flags, status of the mouse */
118#define MOUSE_VISIBLE0x01 0x01 /* flag, the mouse cursor is visible */
119#define SEL_EXISTS0x02 0x02 /* flag, a selection exists */
120#define SEL_IN_PROGRESS0x04 0x04 /* flag, a selection is in progress */
121#define SEL_EXT_AFTER0x08 0x08 /* flag, selection is extended after */
122#define BLANK_TO_EOL0x10 0x10 /* flag, there are only blanks
123 characters to eol */
124#define SEL_BY_CHAR0x20 0x20 /* flag, select character by character*/
125#define SEL_BY_WORD0x40 0x40 /* flag, select word by word */
126#define SEL_BY_LINE0x80 0x80 /* flag, select line by line */
127
128#define IS_MOUSE_VISIBLE(scr)((scr)->mouse_flags & 0x01) ((scr)->mouse_flags & MOUSE_VISIBLE0x01)
129#define IS_SEL_EXISTS(scr)((scr)->mouse_flags & 0x02) ((scr)->mouse_flags & SEL_EXISTS0x02)
130#define IS_SEL_IN_PROGRESS(scr)((scr)->mouse_flags & 0x04) ((scr)->mouse_flags & SEL_IN_PROGRESS0x04)
131#define IS_SEL_EXT_AFTER(scr)((scr)->mouse_flags & 0x08) ((scr)->mouse_flags & SEL_EXT_AFTER0x08)
132#define IS_BLANK_TO_EOL(scr)((scr)->mouse_flags & 0x10) ((scr)->mouse_flags & BLANK_TO_EOL0x10)
133#define IS_SEL_BY_CHAR(scr)((scr)->mouse_flags & 0x20) ((scr)->mouse_flags & SEL_BY_CHAR0x20)
134#define IS_SEL_BY_WORD(scr)((scr)->mouse_flags & 0x40) ((scr)->mouse_flags & SEL_BY_WORD0x40)
135#define IS_SEL_BY_LINE(scr)((scr)->mouse_flags & 0x80) ((scr)->mouse_flags & SEL_BY_LINE0x80)
136#endif /* HAVE_WSMOUSED_SUPPORT */
137};
138
139struct wsscreen *wsscreen_attach(struct wsdisplay_softc *, int, const char *,
140 const struct wsscreen_descr *, void *, int, int, uint32_t);
141void wsscreen_detach(struct wsscreen *);
142int wsdisplay_addscreen(struct wsdisplay_softc *, int, const char *,
143 const char *);
144int wsdisplay_getscreen(struct wsdisplay_softc *,
145 struct wsdisplay_addscreendata *);
146void wsdisplay_resume_device(struct device *);
147void wsdisplay_suspend_device(struct device *);
148void wsdisplay_addscreen_print(struct wsdisplay_softc *, int, int);
149void wsdisplay_closescreen(struct wsdisplay_softc *, struct wsscreen *);
150int wsdisplay_delscreen(struct wsdisplay_softc *, int, int);
151
152void wsdisplay_burner_setup(struct wsdisplay_softc *, struct wsscreen *);
153void wsdisplay_burner(void *v);
154
155struct wsdisplay_softc {
156 struct device sc_dv;
157
158 const struct wsdisplay_accessops *sc_accessops;
159 void *sc_accesscookie;
160
161 const struct wsscreen_list *sc_scrdata;
162
163 struct wsscreen *sc_scr[WSDISPLAY_MAXSCREEN12];
164 int sc_focusidx; /* available only if sc_focus isn't null */
165 struct wsscreen *sc_focus;
166
167#ifdef HAVE_BURNER_SUPPORT
168 struct timeout sc_burner;
169 int sc_burnoutintvl; /* delay before blanking (ms) */
170 int sc_burninintvl; /* delay before unblanking (ms) */
171 int sc_burnout; /* current sc_burner delay (ms) */
172 int sc_burnman; /* nonzero if screen blanked */
173 int sc_burnflags;
174#endif
175
176 int sc_isconsole;
177
178 int sc_flags;
179#define SC_SWITCHPENDING0x01 0x01
180#define SC_PASTE_AVAIL0x02 0x02
181 int sc_screenwanted, sc_oldscreen; /* valid with SC_SWITCHPENDING */
182 int sc_resumescreen; /* if set, can't switch until resume. */
183
184#if NWSKBD1 > 0
185 struct wsevsrc *sc_input;
186#ifdef WSDISPLAY_COMPAT_RAWKBD1
187 int sc_rawkbd;
188#endif
189#endif /* NWSKBD > 0 */
190
191#ifdef HAVE_WSMOUSED_SUPPORT
192 char *sc_copybuffer;
193 u_int sc_copybuffer_size;
194#endif
195};
196
197extern struct cfdriver wsdisplay_cd;
198
199/* Autoconfiguration definitions. */
200int wsdisplay_emul_match(struct device *, void *, void *);
201void wsdisplay_emul_attach(struct device *, struct device *, void *);
202int wsdisplay_emul_detach(struct device *, int);
203
204int wsdisplay_activate(struct device *, int);
205
206struct cfdriver wsdisplay_cd = {
207 NULL((void *)0), "wsdisplay", DV_TTY
208};
209
210struct cfattach wsdisplay_emul_ca = {
211 sizeof(struct wsdisplay_softc), wsdisplay_emul_match,
212 wsdisplay_emul_attach, wsdisplay_emul_detach, wsdisplay_activate
213};
214
215void wsdisplaystart(struct tty *);
216int wsdisplayparam(struct tty *, struct termios *);
217
218/* Internal macros, functions, and variables. */
219#define WSDISPLAYUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 8)
(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
>> 8)
220#define WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
& 0xff)
221#define ISWSDISPLAYCTL(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff) == 255)
(WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
== 255)
222#define WSDISPLAYMINOR(unit, screen)(((unit) << 8) | (screen)) (((unit) << 8) | (screen))
223
224#define WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0)) ((scr)->scr_tty != NULL((void *)0))
225
226void wsdisplay_common_attach(struct wsdisplay_softc *sc,
227 int console, int mux, const struct wsscreen_list *,
228 const struct wsdisplay_accessops *accessops,
229 void *accesscookie, u_int defaultscreens);
230int wsdisplay_common_detach(struct wsdisplay_softc *, int);
231void wsdisplay_kbdholdscr(struct wsscreen *, int);
232
233#ifdef WSDISPLAY_COMPAT_RAWKBD1
234int wsdisplay_update_rawkbd(struct wsdisplay_softc *, struct wsscreen *);
235#endif
236
237int wsdisplay_console_initted;
238struct wsdisplay_softc *wsdisplay_console_device;
239struct wsscreen_internal wsdisplay_console_conf;
240
241int wsdisplay_getc_dummy(dev_t);
242void wsdisplay_pollc(dev_t, int);
243
244int wsdisplay_cons_pollmode;
245void (*wsdisplay_cons_kbd_pollc)(dev_t, int);
246
247struct consdev wsdisplay_cons = {
248 NULL((void *)0), NULL((void *)0), wsdisplay_getc_dummy, wsdisplay_cnputc,
249 wsdisplay_pollc, NULL((void *)0), NODEV(dev_t)(-1), CN_LOWPRI1
250};
251
252/*
253 * Function pointers for wsconsctl parameter handling.
254 * These are used for firmware-provided display brightness control.
255 */
256int (*ws_get_param)(struct wsdisplay_param *);
257int (*ws_set_param)(struct wsdisplay_param *);
258
259
260#ifndef WSDISPLAY_DEFAULTSCREENS6
261#define WSDISPLAY_DEFAULTSCREENS6 1
262#endif
263int wsdisplay_defaultscreens = WSDISPLAY_DEFAULTSCREENS6;
264
265int wsdisplay_switch1(void *, int, int);
266int wsdisplay_switch2(void *, int, int);
267int wsdisplay_switch3(void *, int, int);
268
269int wsdisplay_clearonclose;
270
271struct wsscreen *
272wsscreen_attach(struct wsdisplay_softc *sc, int console, const char *emul,
273 const struct wsscreen_descr *type, void *cookie, int ccol, int crow,
274 uint32_t defattr)
275{
276 struct wsscreen_internal *dconf;
277 struct wsscreen *scr;
278
279 scr = malloc(sizeof(*scr), M_DEVBUF2, M_ZERO0x0008 | M_NOWAIT0x0002);
280 if (!scr)
281 return (NULL((void *)0));
282
283 if (console) {
284 dconf = &wsdisplay_console_conf;
285 /*
286 * Tell the emulation about the callback argument.
287 * The other stuff is already there.
288 */
289 (void)(*dconf->wsemul->attach)(1, 0, 0, 0, 0, scr, 0);
290 } else { /* not console */
291 dconf = malloc(sizeof(*dconf), M_DEVBUF2, M_NOWAIT0x0002);
292 if (dconf == NULL((void *)0))
293 goto fail;
294 dconf->emulops = type->textops;
295 dconf->emulcookie = cookie;
296 if (dconf->emulops == NULL((void *)0) ||
297 (dconf->wsemul = wsemul_pick(emul)) == NULL((void *)0))
298 goto fail;
299 dconf->wsemulcookie = (*dconf->wsemul->attach)(0, type, cookie,
300 ccol, crow, scr, defattr);
301 if (dconf->wsemulcookie == NULL((void *)0))
302 goto fail;
303 dconf->scrdata = type;
304 }
305
306 scr->scr_dconf = dconf;
307 scr->scr_tty = ttymalloc(0);
308 scr->sc = sc;
309 return (scr);
310
311fail:
312 if (dconf != NULL((void *)0))
313 free(dconf, M_DEVBUF2, sizeof(*dconf));
314 free(scr, M_DEVBUF2, sizeof(*scr));
315 return (NULL((void *)0));
316}
317
318void
319wsscreen_detach(struct wsscreen *scr)
320{
321 int ccol, crow; /* XXX */
322
323 if (WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0))) {
324 timeout_del(&scr->scr_tty->t_rstrt_to);
325 ttyfree(scr->scr_tty);
326 }
327 (*scr->scr_dconf->wsemul->detach)(scr->scr_dconf->wsemulcookie,
328 &ccol, &crow);
329 free(scr->scr_dconf, M_DEVBUF2, sizeof(*scr->scr_dconf));
330 free(scr, M_DEVBUF2, sizeof(*scr));
331}
332
333const struct wsscreen_descr *
334wsdisplay_screentype_pick(const struct wsscreen_list *scrdata, const char *name)
335{
336 int i;
337 const struct wsscreen_descr *scr;
338
339 KASSERT(scrdata->nscreens > 0)((scrdata->nscreens > 0) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/wscons/wsdisplay.c", 339, "scrdata->nscreens > 0"
))
;
340
341 if (name == NULL((void *)0) || *name == '\0')
342 return (scrdata->screens[0]);
343
344 for (i = 0; i < scrdata->nscreens; i++) {
345 scr = scrdata->screens[i];
346 if (!strncmp(name, scr->name, WSSCREEN_NAME_SIZE16))
347 return (scr);
348 }
349
350 return (0);
351}
352
353/*
354 * print info about attached screen
355 */
356void
357wsdisplay_addscreen_print(struct wsdisplay_softc *sc, int idx, int count)
358{
359 printf("%s: screen %d", sc->sc_dv.dv_xname, idx);
360 if (count > 1)
361 printf("-%d", idx + (count-1));
362 printf(" added (%s, %s emulation)\n",
363 sc->sc_scr[idx]->scr_dconf->scrdata->name,
364 sc->sc_scr[idx]->scr_dconf->wsemul->name);
365}
366
367int
368wsdisplay_addscreen(struct wsdisplay_softc *sc, int idx,
369 const char *screentype, const char *emul)
370{
371 const struct wsscreen_descr *scrdesc;
372 int error;
373 void *cookie;
374 int ccol, crow;
375 uint32_t defattr;
376 struct wsscreen *scr;
377 int s;
378
379 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN12)
380 return (EINVAL22);
381 if (sc->sc_scr[idx] != NULL((void *)0))
382 return (EBUSY16);
383
384 scrdesc = wsdisplay_screentype_pick(sc->sc_scrdata, screentype);
385 if (!scrdesc)
386 return (ENXIO6);
387 error = (*sc->sc_accessops->alloc_screen)(sc->sc_accesscookie,
388 scrdesc, &cookie, &ccol, &crow, &defattr);
389 if (error)
390 return (error);
391
392 scr = wsscreen_attach(sc, 0, emul, scrdesc,
393 cookie, ccol, crow, defattr);
394 if (scr == NULL((void *)0)) {
395 (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, cookie);
396 return (ENXIO6);
397 }
398
399 sc->sc_scr[idx] = scr;
400
401 /* if no screen has focus yet, activate the first we get */
402 s = spltty()splraise(0x9);
403 if (!sc->sc_focus) {
404 (*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
405 scr->scr_dconf->emulcookie, 0, 0, 0);
406 sc->sc_focusidx = idx;
407 sc->sc_focus = scr;
408 }
409 splx(s)spllower(s);
410
411#ifdef HAVE_WSMOUSED_SUPPORT
412 allocate_copybuffer(sc); /* enlarge the copy buffer if necessary */
413#endif
414 return (0);
415}
416
417int
418wsdisplay_getscreen(struct wsdisplay_softc *sc,
419 struct wsdisplay_addscreendata *sd)
420{
421 struct wsscreen *scr;
422
423 if (sd->idx < 0 && sc->sc_focus)
424 sd->idx = sc->sc_focusidx;
425
426 if (sd->idx < 0 || sd->idx >= WSDISPLAY_MAXSCREEN12)
427 return (EINVAL22);
428
429 scr = sc->sc_scr[sd->idx];
430 if (scr == NULL((void *)0))
431 return (ENXIO6);
432
433 strlcpy(sd->screentype, scr->scr_dconf->scrdata->name,
434 WSSCREEN_NAME_SIZE16);
435 strlcpy(sd->emul, scr->scr_dconf->wsemul->name, WSEMUL_NAME_SIZE16);
436
437 return (0);
438}
439
440void
441wsdisplay_closescreen(struct wsdisplay_softc *sc, struct wsscreen *scr)
442{
443 int maj, mn, idx;
444
445 /* hangup */
446 if (WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0))) {
447 struct tty *tp = scr->scr_tty;
448 (*linesw[tp->t_line].l_modem)(tp, 0);
449 }
450
451 /* locate the major number */
452 for (maj = 0; maj < nchrdev; maj++)
453 if (cdevsw[maj].d_open == wsdisplayopen)
454 break;
455 /* locate the screen index */
456 for (idx = 0; idx < WSDISPLAY_MAXSCREEN12; idx++)
457 if (scr == sc->sc_scr[idx])
458 break;
459#ifdef DIAGNOSTIC1
460 if (idx == WSDISPLAY_MAXSCREEN12)
461 panic("wsdisplay_forceclose: bad screen");
462#endif
463
464 /* nuke the vnodes */
465 mn = WSDISPLAYMINOR(sc->sc_dv.dv_unit, idx)(((sc->sc_dv.dv_unit) << 8) | (idx));
466 vdevgone(maj, mn, mn, VCHR);
467}
468
469int
470wsdisplay_delscreen(struct wsdisplay_softc *sc, int idx, int flags)
471{
472 struct wsscreen *scr;
473 int s;
474 void *cookie;
475
476 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN12)
477 return (EINVAL22);
478 if ((scr = sc->sc_scr[idx]) == NULL((void *)0))
479 return (ENXIO6);
480
481 if (scr->scr_dconf == &wsdisplay_console_conf ||
482#ifdef WSDISPLAY_COMPAT_USL1
483 scr->scr_syncops ||
484#endif
485 ((scr->scr_flags & SCR_OPEN1) && !(flags & WSDISPLAY_DELSCR_FORCE0x01)))
486 return (EBUSY16);
487
488 wsdisplay_closescreen(sc, scr);
489
490 /*
491 * delete pointers, so neither device entries
492 * nor keyboard input can reference it anymore
493 */
494 s = spltty()splraise(0x9);
495 if (sc->sc_focus == scr) {
496 sc->sc_focus = NULL((void *)0);
497#ifdef WSDISPLAY_COMPAT_RAWKBD1
498 wsdisplay_update_rawkbd(sc, 0);
499#endif
500 }
501 sc->sc_scr[idx] = NULL((void *)0);
502 splx(s)spllower(s);
503
504 /*
505 * Wake up processes waiting for the screen to
506 * be activated. Sleepers must check whether
507 * the screen still exists.
508 */
509 if (scr->scr_flags & SCR_WAITACTIVE2)
510 wakeup(scr);
511
512 /* save a reference to the graphics screen */
513 cookie = scr->scr_dconf->emulcookie;
514
515 wsscreen_detach(scr);
516
517 (*sc->sc_accessops->free_screen)(sc->sc_accesscookie, cookie);
518
519 if ((flags & WSDISPLAY_DELSCR_QUIET0x02) == 0)
520 printf("%s: screen %d deleted\n", sc->sc_dv.dv_xname, idx);
521 return (0);
522}
523
524/*
525 * Autoconfiguration functions.
526 */
527int
528wsdisplay_emul_match(struct device *parent, void *match, void *aux)
529{
530 struct cfdata *cf = match;
531 struct wsemuldisplaydev_attach_args *ap = aux;
532
533 if (cf->wsemuldisplaydevcf_consolecf_loc[0] != WSEMULDISPLAYDEVCF_CONSOLE_UNK-1) {
534 /*
535 * If console-ness of device specified, either match
536 * exactly (at high priority), or fail.
537 */
538 if (cf->wsemuldisplaydevcf_consolecf_loc[0] != 0 && ap->console != 0)
539 return (10);
540 else
541 return (0);
542 }
543
544 if (cf->wsemuldisplaydevcf_primarycf_loc[1] != WSEMULDISPLAYDEVCF_PRIMARY_UNK-1) {
545 /*
546 * If primary-ness of device specified, either match
547 * exactly (at high priority), or fail.
548 */
549 if (cf->wsemuldisplaydevcf_primarycf_loc[1] != 0 && ap->primary != 0)
550 return (10);
551 else
552 return (0);
553 }
554
555 /* If console-ness and primary-ness unspecified, it wins. */
556 return (1);
557}
558
559void
560wsdisplay_emul_attach(struct device *parent, struct device *self, void *aux)
561{
562 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self;
563 struct wsemuldisplaydev_attach_args *ap = aux;
564
565 wsdisplay_common_attach(sc, ap->console,
566 sc->sc_dv.dv_cfdata->wsemuldisplaydevcf_muxcf_loc[2], ap->scrdata,
567 ap->accessops, ap->accesscookie, ap->defaultscreens);
568
569 if (ap->console && cn_tab == &wsdisplay_cons) {
570 int maj;
571
572 /* locate the major number */
573 for (maj = 0; maj < nchrdev; maj++)
574 if (cdevsw[maj].d_open == wsdisplayopen)
575 break;
576
577 cn_tab->cn_dev = makedev(maj, WSDISPLAYMINOR(self->dv_unit, 0))((dev_t)((((maj) & 0xff) << 8) | (((((self->dv_unit
) << 8) | (0))) & 0xff) | ((((((self->dv_unit) <<
8) | (0))) & 0xffff00) << 8)))
;
578 }
579}
580
581/*
582 * Detach a display.
583 */
584int
585wsdisplay_emul_detach(struct device *self, int flags)
586{
587 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)self;
588
589 return (wsdisplay_common_detach(sc, flags));
590}
591
592int
593wsdisplay_activate(struct device *self, int act)
594{
595 int ret = 0;
596
597 switch (act) {
598 case DVACT_POWERDOWN6:
599 wsdisplay_switchtoconsole();
600 break;
601 }
602
603 return (ret);
604}
605
606int
607wsdisplay_common_detach(struct wsdisplay_softc *sc, int flags)
608{
609 int i;
610 int rc;
611
612 /* We don't support detaching the console display yet. */
613 if (sc->sc_isconsole)
614 return (EBUSY16);
615
616 /* Delete all screens managed by this display */
617 for (i = 0; i < WSDISPLAY_MAXSCREEN12; i++)
618 if (sc->sc_scr[i] != NULL((void *)0)) {
619 if ((rc = wsdisplay_delscreen(sc, i,
620 WSDISPLAY_DELSCR_QUIET0x02 | (flags & DETACH_FORCE0x01 ?
621 WSDISPLAY_DELSCR_FORCE0x01 : 0))) != 0)
622 return (rc);
623 }
624
625#ifdef HAVE_BURNER_SUPPORT
626 timeout_del(&sc->sc_burner);
627#endif
628
629#if NWSKBD1 > 0
630 if (sc->sc_input != NULL((void *)0)) {
631#if NWSMUX1 > 0
632 /*
633 * If we are the display of the mux we are attached to,
634 * disconnect all input devices from us.
635 */
636 if (sc->sc_input->me_dispdv == &sc->sc_dv) {
637 if ((rc = wsmux_set_display((struct wsmux_softc *)
638 sc->sc_input, NULL((void *)0))) != 0)
639 return (rc);
640 }
641
642 /*
643 * XXX
644 * If we created a standalone mux (dmux), we should destroy it
645 * there, but there is currently no support for this in wsmux.
646 */
647#else
648 if ((rc = wskbd_set_display((struct device *)sc->sc_input,
649 NULL((void *)0))) != 0)
650 return (rc);
651#endif
652 }
653#endif
654
655 return (0);
656}
657
658/* Print function (for parent devices). */
659int
660wsemuldisplaydevprint(void *aux, const char *pnp)
661{
662#if 0 /* -Wunused */
663 struct wsemuldisplaydev_attach_args *ap = aux;
664#endif
665
666 if (pnp)
667 printf("wsdisplay at %s", pnp);
668#if 0 /* don't bother; it's ugly */
669 printf(" console %d", ap->console);
670#endif
671
672 return (UNCONF1);
673}
674
675/* Submatch function (for parent devices). */
676int
677wsemuldisplaydevsubmatch(struct device *parent, void *match, void *aux)
678{
679 extern struct cfdriver wsdisplay_cd;
680 struct cfdata *cf = match;
681
682 /* only allow wsdisplay to attach */
683 if (cf->cf_driver == &wsdisplay_cd)
684 return ((*cf->cf_attach->ca_match)(parent, match, aux));
685
686 return (0);
687}
688
689void
690wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux,
691 const struct wsscreen_list *scrdata,
692 const struct wsdisplay_accessops *accessops, void *accesscookie,
693 u_int defaultscreens)
694{
695 int i, start = 0;
696#if NWSKBD1 > 0
697 struct wsevsrc *kme;
698#if NWSMUX1 > 0
699 struct wsmux_softc *mux;
700
701 if (kbdmux >= 0)
702 mux = wsmux_getmux(kbdmux);
703 else
704 mux = wsmux_create("dmux", sc->sc_dv.dv_unit);
705 /* XXX panic()ing isn't nice, but attach cannot fail */
706 if (mux == NULL((void *)0))
707 panic("wsdisplay_common_attach: no memory");
708 sc->sc_input = &mux->sc_base;
709
710 if (kbdmux >= 0)
711 printf(" mux %d", kbdmux);
712#else
713#if 0 /* not worth keeping, especially since the default value is not -1... */
714 if (kbdmux >= 0)
715 printf(" (mux ignored)");
716#endif
717#endif /* NWSMUX > 0 */
718#endif /* NWSKBD > 0 */
719
720 sc->sc_isconsole = console;
721 sc->sc_resumescreen = WSDISPLAY_NULLSCREEN-1;
722
723 if (console) {
724 KASSERT(wsdisplay_console_initted)((wsdisplay_console_initted) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/wscons/wsdisplay.c", 724, "wsdisplay_console_initted"
))
;
725 KASSERT(wsdisplay_console_device == NULL)((wsdisplay_console_device == ((void *)0)) ? (void)0 : __assert
("diagnostic ", "/usr/src/sys/dev/wscons/wsdisplay.c", 725, "wsdisplay_console_device == NULL"
))
;
726
727 sc->sc_scr[0] = wsscreen_attach(sc, 1, 0, 0, 0, 0, 0, 0);
728 if (sc->sc_scr[0] == NULL((void *)0))
729 return;
730 wsdisplay_console_device = sc;
731
732 printf(": console (%s, %s emulation)",
733 wsdisplay_console_conf.scrdata->name,
734 wsdisplay_console_conf.wsemul->name);
735
736#if NWSKBD1 > 0
737 kme = wskbd_set_console_display(&sc->sc_dv, sc->sc_input);
738 if (kme != NULL((void *)0))
739 printf(", using %s", kme->me_dv.dv_xname);
740#if NWSMUX1 == 0
741 sc->sc_input = kme;
742#endif
743#endif
744
745 sc->sc_focusidx = 0;
746 sc->sc_focus = sc->sc_scr[0];
747 start = 1;
748 }
749 printf("\n");
750
751#if NWSKBD1 > 0 && NWSMUX1 > 0
752 /*
753 * If this mux did not have a display device yet, volunteer for
754 * the job.
755 */
756 if (mux->sc_displaydvsc_base.me_dispdv == NULL((void *)0))
757 wsmux_set_display(mux, &sc->sc_dv);
758#endif
759
760 sc->sc_accessops = accessops;
761 sc->sc_accesscookie = accesscookie;
762 sc->sc_scrdata = scrdata;
763
764 /*
765 * Set up a number of virtual screens if wanted. The
766 * WSDISPLAYIO_ADDSCREEN ioctl is more flexible, so this code
767 * is for special cases like installation kernels, as well as
768 * sane multihead defaults.
769 */
770 if (defaultscreens == 0)
771 defaultscreens = wsdisplay_defaultscreens;
772 for (i = start; i < defaultscreens; i++) {
773 if (wsdisplay_addscreen(sc, i, 0, 0))
774 break;
775 }
776
777 if (i > start)
778 wsdisplay_addscreen_print(sc, start, i-start);
779
780#ifdef HAVE_BURNER_SUPPORT
781 sc->sc_burnoutintvl = WSDISPLAY_DEFBURNOUT_MSEC0;
782 sc->sc_burninintvl = WSDISPLAY_DEFBURNIN_MSEC250;
783 sc->sc_burnflags = WSDISPLAY_BURN_OUTPUT0x0008 | WSDISPLAY_BURN_KBD0x0002 |
784 WSDISPLAY_BURN_MOUSE0x0004;
785 timeout_set(&sc->sc_burner, wsdisplay_burner, sc);
786 sc->sc_burnout = sc->sc_burnoutintvl;
787 wsdisplay_burn(sc, sc->sc_burnflags);
788#endif
789
790#if NWSKBD1 > 0 && NWSMUX1 == 0
791 if (console == 0) {
792 /*
793 * In the non-wsmux world, always connect wskbd0 and wsdisplay0
794 * together.
795 */
796 extern struct cfdriver wskbd_cd;
797
798 if (wskbd_cd.cd_ndevs != 0 && sc->sc_dv.dv_unit == 0) {
799 if (wsdisplay_set_kbd(&sc->sc_dv,
800 (struct wsevsrc *)wskbd_cd.cd_devs[0]) == 0)
801 wskbd_set_display(wskbd_cd.cd_devs[0],
802 &sc->sc_dv);
803 }
804 }
805#endif
806}
807
808void
809wsdisplay_cnattach(const struct wsscreen_descr *type, void *cookie, int ccol,
810 int crow, uint32_t defattr)
811{
812 const struct wsemul_ops *wsemul;
813 const struct wsdisplay_emulops *emulops;
814
815 KASSERT(type->nrows > 0)((type->nrows > 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/wscons/wsdisplay.c"
, 815, "type->nrows > 0"))
;
816 KASSERT(type->ncols > 0)((type->ncols > 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/wscons/wsdisplay.c"
, 816, "type->ncols > 0"))
;
817 KASSERT(crow < type->nrows)((crow < type->nrows) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/wscons/wsdisplay.c", 817, "crow < type->nrows"
))
;
818 KASSERT(ccol < type->ncols)((ccol < type->ncols) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/wscons/wsdisplay.c", 818, "ccol < type->ncols"
))
;
819
820 wsdisplay_console_conf.emulops = emulops = type->textops;
Although the value stored to 'emulops' is used in the enclosing expression, the value is never actually read from 'emulops'
821 wsdisplay_console_conf.emulcookie = cookie;
822 wsdisplay_console_conf.scrdata = type;
823
824#ifdef WSEMUL_DUMB
825 /*
826 * If the emulops structure is crippled, force a dumb emulation.
827 */
828 if (emulops->cursor == NULL((void *)0) ||
829 emulops->copycols == NULL((void *)0) || emulops->copyrows == NULL((void *)0) ||
830 emulops->erasecols == NULL((void *)0) || emulops->eraserows == NULL((void *)0))
831 wsemul = wsemul_pick("dumb");
832 else
833#endif
834 wsemul = wsemul_pick("");
835 wsdisplay_console_conf.wsemul = wsemul;
836 wsdisplay_console_conf.wsemulcookie =
837 (*wsemul->cnattach)(type, cookie, ccol, crow, defattr);
838
839 if (!wsdisplay_console_initted)
840 cn_tab = &wsdisplay_cons;
841
842 wsdisplay_console_initted = 1;
843
844#ifdef DDB1
845 db_resize(type->ncols, type->nrows);
846#endif
847}
848
849/*
850 * Tty and cdevsw functions.
851 */
852int
853wsdisplayopen(dev_t dev, int flag, int mode, struct proc *p)
854{
855 struct wsdisplay_softc *sc;
856 struct tty *tp;
857 int unit, newopen, error;
858 struct wsscreen *scr;
859
860 unit = WSDISPLAYUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 8)
;
861 if (unit >= wsdisplay_cd.cd_ndevs || /* make sure it was attached */
862 (sc = wsdisplay_cd.cd_devs[unit]) == NULL((void *)0))
863 return (ENXIO6);
864
865 if (ISWSDISPLAYCTL(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff) == 255)
)
866 return (0);
867
868 if (WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
>= WSDISPLAY_MAXSCREEN12)
869 return (ENXIO6);
870 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
]) == NULL((void *)0))
871 return (ENXIO6);
872
873 if (WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0))) {
874 tp = scr->scr_tty;
875 tp->t_oproc = wsdisplaystart;
876 tp->t_param = wsdisplayparam;
877 tp->t_dev = dev;
878 newopen = (tp->t_state & TS_ISOPEN0x00020) == 0;
879 if (newopen) {
880 ttychars(tp);
881 tp->t_iflagt_termios.c_iflag = TTYDEF_IFLAG(0x00000002 | 0x00000100 | 0x00002000 | 0x00000200 | 0x00000800
)
;
882 tp->t_oflagt_termios.c_oflag = TTYDEF_OFLAG(0x00000001 | 0x00000002);
883 tp->t_cflagt_termios.c_cflag = TTYDEF_CFLAG(0x00000800 | 0x00000300 | 0x00004000);
884 tp->t_lflagt_termios.c_lflag = TTYDEF_LFLAG(0x00000008 | 0x00000100 | 0x00000080 | 0x00000400 | 0x00000002
|0x00000001|0x00000040)
;
885 tp->t_ispeedt_termios.c_ispeed = tp->t_ospeedt_termios.c_ospeed = TTYDEF_SPEED(9600);
886 wsdisplayparam(tp, &tp->t_termios);
887 ttsetwater(tp);
888 } else if ((tp->t_state & TS_XCLUDE0x00400) != 0 &&
889 suser(p) != 0)
890 return (EBUSY16);
891 tp->t_state |= TS_CARR_ON0x00008;
892
893 error = ((*linesw[tp->t_line].l_open)(dev, tp, p));
894 if (error)
895 return (error);
896
897 if (newopen) {
898 /* set window sizes as appropriate, and reset
899 the emulation */
900 tp->t_winsize.ws_row = scr->scr_dconf->scrdata->nrows;
901 tp->t_winsize.ws_col = scr->scr_dconf->scrdata->ncols;
902 }
903 }
904
905 scr->scr_flags |= SCR_OPEN1;
906 return (0);
907}
908
909int
910wsdisplayclose(dev_t dev, int flag, int mode, struct proc *p)
911{
912 struct wsdisplay_softc *sc;
913 struct tty *tp;
914 int unit;
915 struct wsscreen *scr;
916
917 unit = WSDISPLAYUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 8)
;
918 sc = wsdisplay_cd.cd_devs[unit];
919
920 if (ISWSDISPLAYCTL(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff) == 255)
)
921 return (0);
922
923 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
]) == NULL((void *)0))
924 return (ENXIO6);
925
926 if (WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0))) {
927 if (scr->scr_hold_screen) {
928 int s;
929
930 /* XXX RESET KEYBOARD LEDS, etc. */
931 s = spltty()splraise(0x9); /* avoid conflict with keyboard */
932 wsdisplay_kbdholdscr(scr, 0);
933 splx(s)spllower(s);
934 }
935 tp = scr->scr_tty;
936 (*linesw[tp->t_line].l_close)(tp, flag, p);
937 ttyclose(tp);
938 }
939
940#ifdef WSDISPLAY_COMPAT_USL1
941 if (scr->scr_syncops)
942 (*scr->scr_syncops->destroy)(scr->scr_synccookie);
943#endif
944
945 scr->scr_flags &= ~SCR_GRAPHICS4;
946 (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie,
947 WSEMUL_RESET);
948 if (wsdisplay_clearonclose)
949 (*scr->scr_dconf->wsemul->reset)
950 (scr->scr_dconf->wsemulcookie, WSEMUL_CLEARSCREEN);
951
952#ifdef WSDISPLAY_COMPAT_RAWKBD1
953 if (scr->scr_rawkbd) {
954 int kbmode = WSKBD_TRANSLATED0;
955 (void) wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('W')) << 8) | ((19)))
,
956 (caddr_t)&kbmode, FWRITE0x0002, p);
957 }
958#endif
959
960 scr->scr_flags &= ~SCR_OPEN1;
961
962#ifdef HAVE_WSMOUSED_SUPPORT
963 /* remove the selection at logout */
964 if (sc->sc_copybuffer != NULL((void *)0))
965 explicit_bzero(sc->sc_copybuffer, sc->sc_copybuffer_size);
966 CLR(sc->sc_flags, SC_PASTE_AVAIL)((sc->sc_flags) &= ~(0x02));
967#endif
968
969 return (0);
970}
971
972int
973wsdisplayread(dev_t dev, struct uio *uio, int flag)
974{
975 struct wsdisplay_softc *sc;
976 struct tty *tp;
977 int unit;
978 struct wsscreen *scr;
979
980 unit = WSDISPLAYUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 8)
;
981 sc = wsdisplay_cd.cd_devs[unit];
982
983 if (ISWSDISPLAYCTL(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff) == 255)
)
984 return (0);
985
986 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
]) == NULL((void *)0))
987 return (ENXIO6);
988
989 if (!WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0)))
990 return (ENODEV19);
991
992 tp = scr->scr_tty;
993 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
994}
995
996int
997wsdisplaywrite(dev_t dev, struct uio *uio, int flag)
998{
999 struct wsdisplay_softc *sc;
1000 struct tty *tp;
1001 int unit;
1002 struct wsscreen *scr;
1003
1004 unit = WSDISPLAYUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 8)
;
1005 sc = wsdisplay_cd.cd_devs[unit];
1006
1007 if (ISWSDISPLAYCTL(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff) == 255)
)
1008 return (0);
1009
1010 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
]) == NULL((void *)0))
1011 return (ENXIO6);
1012
1013 if (!WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0)))
1014 return (ENODEV19);
1015
1016 tp = scr->scr_tty;
1017 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
1018}
1019
1020struct tty *
1021wsdisplaytty(dev_t dev)
1022{
1023 struct wsdisplay_softc *sc;
1024 int unit;
1025 struct wsscreen *scr;
1026
1027 unit = WSDISPLAYUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 8)
;
1028 sc = wsdisplay_cd.cd_devs[unit];
1029
1030 if (ISWSDISPLAYCTL(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff) == 255)
)
1031 panic("wsdisplaytty() on ctl device");
1032
1033 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
]) == NULL((void *)0))
1034 return (NULL((void *)0));
1035
1036 return (scr->scr_tty);
1037}
1038
1039int
1040wsdisplayioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
1041{
1042 struct wsdisplay_softc *sc;
1043 struct tty *tp;
1044 int unit, error;
1045 struct wsscreen *scr;
1046
1047 unit = WSDISPLAYUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 8)
;
1048 sc = wsdisplay_cd.cd_devs[unit];
1049
1050#ifdef WSDISPLAY_COMPAT_USL1
1051 error = wsdisplay_usl_ioctl1(sc, cmd, data, flag, p);
1052 if (error >= 0)
1053 return (error);
1054#endif
1055
1056 if (ISWSDISPLAYCTL(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff) == 255)
) {
1057 switch (cmd) {
1058 case WSDISPLAYIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((64)))
:
1059 case WSDISPLAYIO_GETSCREENTYPE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_screentype) & 0x1fff) << 16) | ((
('W')) << 8) | ((93)))
:
1060 /* pass to the first screen */
1061 dev = makedev(major(dev), WSDISPLAYMINOR(unit, 0))((dev_t)(((((((unsigned)(dev) >> 8) & 0xff)) & 0xff
) << 8) | (((((unit) << 8) | (0))) & 0xff) | (
(((((unit) << 8) | (0))) & 0xffff00) << 8)))
;
1062 break;
1063 default:
1064 return (wsdisplay_cfg_ioctl(sc, cmd, data, flag, p));
1065 }
1066 }
1067
1068 if (WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
>= WSDISPLAY_MAXSCREEN12)
1069 return (ENODEV19);
1070
1071 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
]) == NULL((void *)0))
1072 return (ENXIO6);
1073
1074 if (WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0))) {
1075 tp = scr->scr_tty;
1076
1077/* printf("disc\n"); */
1078 /* do the line discipline ioctls first */
1079 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1080 if (error >= 0)
1081 return (error);
1082
1083/* printf("tty\n"); */
1084 /* then the tty ioctls */
1085 error = ttioctl(tp, cmd, data, flag, p);
1086 if (error >= 0)
1087 return (error);
1088 }
1089
1090#ifdef WSDISPLAY_COMPAT_USL1
1091 error = wsdisplay_usl_ioctl2(sc, scr, cmd, data, flag, p);
1092 if (error >= 0)
1093 return (error);
1094#endif
1095
1096 error = wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, p);
1097 return (error != -1 ? error : ENOTTY25);
1098}
1099
1100int
1101wsdisplay_param(struct device *dev, u_long cmd, struct wsdisplay_param *dp)
1102{
1103 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
1104
1105 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd,
1106 (caddr_t)dp, 0, NULL((void *)0)));
1107}
1108
1109int
1110wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr,
1111 u_long cmd, caddr_t data, int flag, struct proc *p)
1112{
1113 int error;
1114
1115#if NWSKBD1 > 0
1116 struct wsevsrc *inp;
1117
1118#ifdef WSDISPLAY_COMPAT_RAWKBD1
1119 switch (cmd) {
1120 case WSKBDIO_SETMODE((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('W')) << 8) | ((19)))
:
1121 if ((flag & FWRITE0x0002) == 0)
1122 return (EACCES13);
1123 scr->scr_rawkbd = (*(int *)data == WSKBD_RAW1);
1124 return (wsdisplay_update_rawkbd(sc, scr));
1125 case WSKBDIO_GETMODE((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('W')) << 8) | ((20)))
:
1126 *(int *)data = (scr->scr_rawkbd ?
1127 WSKBD_RAW1 : WSKBD_TRANSLATED0);
1128 return (0);
1129 }
1130#endif
1131 inp = sc->sc_input;
1132 if (inp != NULL((void *)0)) {
1133 error = wsevsrc_display_ioctl(inp, cmd, data, flag, p)((inp)->me_ops->ddispioctl(&(inp)->me_dv, cmd, (
caddr_t)data, flag, p))
;
1134 if (error >= 0)
1135 return (error);
1136 }
1137#endif /* NWSKBD > 0 */
1138
1139 switch (cmd) {
1140 case WSDISPLAYIO_SMODE((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((76)))
:
1141 case WSDISPLAYIO_USEFONT((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_font) &
0x1fff) << 16) | ((('W')) << 8) | ((80)))
:
1142#ifdef HAVE_BURNER_SUPPORT
1143 case WSDISPLAYIO_SVIDEO((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((69)))
:
1144 case WSDISPLAYIO_SBURNER((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_burner
) & 0x1fff) << 16) | ((('W')) << 8) | ((81)))
:
1145#endif
1146 case WSDISPLAYIO_SETSCREEN((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((86)))
:
1147 if ((flag & FWRITE0x0002) == 0)
1148 return (EACCES13);
1149 }
1150
1151 switch (cmd) {
1152 case WSDISPLAYIO_GMODE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((75)))
:
1153 if (scr->scr_flags & SCR_GRAPHICS4) {
1154 if (scr->scr_flags & SCR_DUMBFB8)
1155 *(u_int *)data = WSDISPLAYIO_MODE_DUMBFB2;
1156 else
1157 *(u_int *)data = WSDISPLAYIO_MODE_MAPPED1;
1158 } else
1159 *(u_int *)data = WSDISPLAYIO_MODE_EMUL0;
1160 return (0);
1161
1162 case WSDISPLAYIO_SMODE((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((76)))
:
1163#define d (*(int *)data)
1164 if (d != WSDISPLAYIO_MODE_EMUL0 &&
1165 d != WSDISPLAYIO_MODE_MAPPED1 &&
1166 d != WSDISPLAYIO_MODE_DUMBFB2)
1167 return (EINVAL22);
1168
1169 scr->scr_flags &= ~SCR_GRAPHICS4;
1170 if (d == WSDISPLAYIO_MODE_MAPPED1 ||
1171 d == WSDISPLAYIO_MODE_DUMBFB2) {
1172 scr->scr_flags |= SCR_GRAPHICS4 |
1173 ((d == WSDISPLAYIO_MODE_DUMBFB2) ? SCR_DUMBFB8 : 0);
1174
1175 /* clear cursor */
1176 (*scr->scr_dconf->wsemul->reset)
1177 (scr->scr_dconf->wsemulcookie, WSEMUL_CLEARCURSOR);
1178 }
1179
1180#ifdef HAVE_BURNER_SUPPORT
1181 wsdisplay_burner_setup(sc, scr);
1182#endif
1183
1184 (void)(*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data,
1185 flag, p);
1186
1187 return (0);
1188#undef d
1189
1190 case WSDISPLAYIO_USEFONT((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_font) &
0x1fff) << 16) | ((('W')) << 8) | ((80)))
:
1191#define d ((struct wsdisplay_font *)data)
1192 if (!sc->sc_accessops->load_font)
1193 return (EINVAL22);
1194 d->data = NULL((void *)0);
1195 error = (*sc->sc_accessops->load_font)(sc->sc_accesscookie,
1196 scr->scr_dconf->emulcookie, d);
1197 if (!error)
1198 (*scr->scr_dconf->wsemul->reset)
1199 (scr->scr_dconf->wsemulcookie, WSEMUL_SYNCFONT);
1200 return (error);
1201#undef d
1202#ifdef HAVE_BURNER_SUPPORT
1203 case WSDISPLAYIO_GVIDEO((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((68)))
:
1204 *(u_int *)data = !sc->sc_burnman;
1205 break;
1206
1207 case WSDISPLAYIO_SVIDEO((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((69)))
:
1208 if (*(u_int *)data != WSDISPLAYIO_VIDEO_OFF0 &&
1209 *(u_int *)data != WSDISPLAYIO_VIDEO_ON1)
1210 return (EINVAL22);
1211 if (sc->sc_accessops->burn_screen == NULL((void *)0))
1212 return (EOPNOTSUPP45);
1213 (*sc->sc_accessops->burn_screen)(sc->sc_accesscookie,
1214 *(u_int *)data, sc->sc_burnflags);
1215 sc->sc_burnman = *(u_int *)data == WSDISPLAYIO_VIDEO_OFF0;
1216 break;
1217
1218 case WSDISPLAYIO_GBURNER((unsigned long)0x40000000 | ((sizeof(struct wsdisplay_burner
) & 0x1fff) << 16) | ((('W')) << 8) | ((82)))
:
1219#define d ((struct wsdisplay_burner *)data)
1220 d->on = sc->sc_burninintvl;
1221 d->off = sc->sc_burnoutintvl;
1222 d->flags = sc->sc_burnflags;
1223 return (0);
1224
1225 case WSDISPLAYIO_SBURNER((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_burner
) & 0x1fff) << 16) | ((('W')) << 8) | ((81)))
:
1226 {
1227 struct wsscreen *active;
1228
1229 if (d->flags & ~(WSDISPLAY_BURN_VBLANK0x0001 | WSDISPLAY_BURN_KBD0x0002 |
1230 WSDISPLAY_BURN_MOUSE0x0004 | WSDISPLAY_BURN_OUTPUT0x0008))
1231 return EINVAL22;
1232
1233 error = 0;
1234 sc->sc_burnflags = d->flags;
1235 /* disable timeout if necessary */
1236 if ((sc->sc_burnflags & (WSDISPLAY_BURN_OUTPUT0x0008 |
1237 WSDISPLAY_BURN_KBD0x0002 | WSDISPLAY_BURN_MOUSE0x0004)) == 0) {
1238 if (sc->sc_burnout)
1239 timeout_del(&sc->sc_burner);
1240 }
1241
1242 active = sc->sc_focus;
1243 if (active == NULL((void *)0))
1244 active = scr;
1245
1246 if (d->on) {
1247 sc->sc_burninintvl = d->on;
1248 if (sc->sc_burnman) {
1249 sc->sc_burnout = sc->sc_burninintvl;
1250 /* reinit timeout if changed */
1251 if ((active->scr_flags & SCR_GRAPHICS4) == 0)
1252 wsdisplay_burn(sc, sc->sc_burnflags);
1253 }
1254 }
1255 if (d->off) {
1256 sc->sc_burnoutintvl = d->off;
1257 if (!sc->sc_burnman) {
1258 sc->sc_burnout = sc->sc_burnoutintvl;
1259 /* reinit timeout if changed */
1260 if ((active->scr_flags & SCR_GRAPHICS4) == 0)
1261 wsdisplay_burn(sc, sc->sc_burnflags);
1262 }
1263 }
1264 return (error);
1265 }
1266#undef d
1267#endif /* HAVE_BURNER_SUPPORT */
1268 case WSDISPLAYIO_GETSCREEN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_addscreendata) & 0x1fff) << 16) |
((('W')) << 8) | ((85)))
:
1269 return (wsdisplay_getscreen(sc,
1270 (struct wsdisplay_addscreendata *)data));
1271
1272 case WSDISPLAYIO_SETSCREEN((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((86)))
:
1273 return (wsdisplay_switch((void *)sc, *(int *)data, 1));
1274
1275 case WSDISPLAYIO_GETSCREENTYPE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_screentype) & 0x1fff) << 16) | ((
('W')) << 8) | ((93)))
:
1276#define d ((struct wsdisplay_screentype *)data)
1277 if (d->idx < 0 || d->idx >= sc->sc_scrdata->nscreens)
1278 return(EINVAL22);
1279
1280 d->nidx = sc->sc_scrdata->nscreens;
1281 strlcpy(d->name, sc->sc_scrdata->screens[d->idx]->name,
1282 WSSCREEN_NAME_SIZE16);
1283 d->ncols = sc->sc_scrdata->screens[d->idx]->ncols;
1284 d->nrows = sc->sc_scrdata->screens[d->idx]->nrows;
1285 d->fontwidth = sc->sc_scrdata->screens[d->idx]->fontwidth;
1286 d->fontheight = sc->sc_scrdata->screens[d->idx]->fontheight;
1287 return (0);
1288#undef d
1289 case WSDISPLAYIO_GETEMULTYPE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_emultype) & 0x1fff) << 16) | ((('W'
)) << 8) | ((94)))
:
1290#define d ((struct wsdisplay_emultype *)data)
1291 if (wsemul_getname(d->idx) == NULL((void *)0))
1292 return(EINVAL22);
1293 strlcpy(d->name, wsemul_getname(d->idx), WSEMUL_NAME_SIZE16);
1294 return (0);
1295#undef d
1296 }
1297
1298 /* check ioctls for display */
1299 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data,
1300 flag, p));
1301}
1302
1303int
1304wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data,
1305 int flag, struct proc *p)
1306{
1307 int error;
1308 void *buf;
1309 size_t fontsz;
1310#if NWSKBD1 > 0
1311 struct wsevsrc *inp;
1312#endif
1313
1314 switch (cmd) {
1315#ifdef HAVE_WSMOUSED_SUPPORT
1316 case WSDISPLAYIO_WSMOUSED((unsigned long)0x80000000 | ((sizeof(struct wscons_event) &
0x1fff) << 16) | ((('W')) << 8) | ((88)))
:
1317 error = wsmoused(sc, data, flag, p);
1318 return (error);
1319#endif
1320 case WSDISPLAYIO_ADDSCREEN((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_addscreendata
) & 0x1fff) << 16) | ((('W')) << 8) | ((83)))
:
1321#define d ((struct wsdisplay_addscreendata *)data)
1322 if ((error = wsdisplay_addscreen(sc, d->idx,
1323 d->screentype, d->emul)) == 0)
1324 wsdisplay_addscreen_print(sc, d->idx, 0);
1325 return (error);
1326#undef d
1327 case WSDISPLAYIO_DELSCREEN((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_delscreendata
) & 0x1fff) << 16) | ((('W')) << 8) | ((84)))
:
1328#define d ((struct wsdisplay_delscreendata *)data)
1329 return (wsdisplay_delscreen(sc, d->idx, d->flags));
1330#undef d
1331 case WSDISPLAYIO_GETSCREEN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_addscreendata) & 0x1fff) << 16) |
((('W')) << 8) | ((85)))
:
1332 return (wsdisplay_getscreen(sc,
1333 (struct wsdisplay_addscreendata *)data));
1334 case WSDISPLAYIO_SETSCREEN((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((86)))
:
1335 return (wsdisplay_switch((void *)sc, *(int *)data, 1));
1336 case WSDISPLAYIO_LDFONT((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_font) &
0x1fff) << 16) | ((('W')) << 8) | ((77)))
:
1337#define d ((struct wsdisplay_font *)data)
1338 if (!sc->sc_accessops->load_font)
1339 return (EINVAL22);
1340 if (d->fontheight > 64 || d->stride > 8) /* 64x64 pixels */
1341 return (EINVAL22);
1342 if (d->numchars > 65536) /* unicode plane */
1343 return (EINVAL22);
1344 fontsz = d->fontheight * d->stride * d->numchars;
1345 if (fontsz > WSDISPLAY_MAXFONTSZ(512*1024))
1346 return (EINVAL22);
1347
1348 buf = malloc(fontsz, M_DEVBUF2, M_WAITOK0x0001);
1349 error = copyin(d->data, buf, fontsz);
1350 if (error) {
1351 free(buf, M_DEVBUF2, fontsz);
1352 return (error);
1353 }
1354 d->data = buf;
1355 error =
1356 (*sc->sc_accessops->load_font)(sc->sc_accesscookie, 0, d);
1357 if (error)
1358 free(buf, M_DEVBUF2, fontsz);
1359 return (error);
1360
1361 case WSDISPLAYIO_LSFONT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_font) & 0x1fff) << 16) | ((('W'))
<< 8) | ((78)))
:
1362 if (!sc->sc_accessops->list_font)
1363 return (EINVAL22);
1364 error =
1365 (*sc->sc_accessops->list_font)(sc->sc_accesscookie, d);
1366 return (error);
1367
1368 case WSDISPLAYIO_DELFONT((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_font) &
0x1fff) << 16) | ((('W')) << 8) | ((79)))
:
1369 return (EINVAL22);
1370#undef d
1371
1372#if NWSKBD1 > 0
1373 case WSMUXIO_ADD_DEVICE((unsigned long)0x80000000 | ((sizeof(struct wsmux_device) &
0x1fff) << 16) | ((('W')) << 8) | ((97)))
:
1374#define d ((struct wsmux_device *)data)
1375 if (d->idx == -1 && d->type == WSMUX_KBD2)
1376 d->idx = wskbd_pickfree();
1377#undef d
1378 /* FALLTHROUGH */
1379 case WSMUXIO_INJECTEVENT((unsigned long)0x80000000 | ((sizeof(struct wscons_event) &
0x1fff) << 16) | ((('W')) << 8) | ((96)))
:
1380 case WSMUXIO_REMOVE_DEVICE((unsigned long)0x80000000 | ((sizeof(struct wsmux_device) &
0x1fff) << 16) | ((('W')) << 8) | ((98)))
:
1381 case WSMUXIO_LIST_DEVICES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsmux_device_list) & 0x1fff) << 16) | ((('W'
)) << 8) | ((99)))
:
1382 inp = sc->sc_input;
1383 if (inp == NULL((void *)0))
1384 return (ENXIO6);
1385 return (wsevsrc_ioctl(inp, cmd, data, flag,p)((inp)->me_ops->dioctl(&(inp)->me_dv, cmd, (caddr_t
)data, flag, p))
);
1386#endif /* NWSKBD > 0 */
1387
1388 }
1389 return (EINVAL22);
1390}
1391
1392paddr_t
1393wsdisplaymmap(dev_t dev, off_t offset, int prot)
1394{
1395 struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 8)
];
1396 struct wsscreen *scr;
1397
1398 if (ISWSDISPLAYCTL(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff) == 255)
)
1399 return (-1);
1400
1401 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
]) == NULL((void *)0))
1402 return (-1);
1403
1404 if (!(scr->scr_flags & SCR_GRAPHICS4))
1405 return (-1);
1406
1407 /* pass mmap to display */
1408 return ((*sc->sc_accessops->mmap)(sc->sc_accesscookie, offset, prot));
1409}
1410
1411int
1412wsdisplaypoll(dev_t dev, int events, struct proc *p)
1413{
1414 struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 8)
];
1415 struct wsscreen *scr;
1416
1417 if (ISWSDISPLAYCTL(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff) == 255)
)
1418 return (0);
1419
1420 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
]) == NULL((void *)0))
1421 return (POLLERR0x0008);
1422
1423 if (!WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0)))
1424 return (POLLERR0x0008);
1425
1426 return (ttpoll(dev, events, p));
1427}
1428
1429int
1430wsdisplaykqfilter(dev_t dev, struct knote *kn)
1431{
1432 struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) >> 8)
];
1433 struct wsscreen *scr;
1434
1435 if (ISWSDISPLAYCTL(dev)((((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff) == 255)
)
1436 return (ENXIO6);
1437
1438 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xff)
]) == NULL((void *)0))
1439 return (ENXIO6);
1440
1441 if (!WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0)))
1442 return (ENXIO6);
1443
1444 return (ttkqfilter(dev, kn));
1445}
1446
1447void
1448wsdisplaystart(struct tty *tp)
1449{
1450 struct wsdisplay_softc *sc;
1451 struct wsscreen *scr;
1452 int s, n, done, unit;
1453 u_char *buf;
1454
1455 unit = WSDISPLAYUNIT(tp->t_dev)(((unsigned)((tp->t_dev) & 0xff) | (((tp->t_dev) &
0xffff0000) >> 8)) >> 8)
;
1456 if (unit >= wsdisplay_cd.cd_ndevs ||
1457 (sc = wsdisplay_cd.cd_devs[unit]) == NULL((void *)0))
1458 return;
1459
1460 s = spltty()splraise(0x9);
1461 if (tp->t_state & (TS_TIMEOUT0x00080 | TS_BUSY0x00004 | TS_TTSTOP0x00100)) {
1462 splx(s)spllower(s);
1463 return;
1464 }
1465 if (tp->t_outq.c_cc == 0 && tp->t_wsel.si_seltid == 0)
1466 goto low;
1467
1468 if ((scr = sc->sc_scr[WSDISPLAYSCREEN(tp->t_dev)(((unsigned)((tp->t_dev) & 0xff) | (((tp->t_dev) &
0xffff0000) >> 8)) & 0xff)
]) == NULL((void *)0)) {
1469 splx(s)spllower(s);
1470 return;
1471 }
1472 if (scr->scr_hold_screen) {
1473 tp->t_state |= TS_TIMEOUT0x00080;
1474 splx(s)spllower(s);
1475 return;
1476 }
1477 tp->t_state |= TS_BUSY0x00004;
1478 splx(s)spllower(s);
1479
1480 /*
1481 * Drain output from ring buffer.
1482 * The output will normally be in one contiguous chunk, but when the
1483 * ring wraps, it will be in two pieces.. one at the end of the ring,
1484 * the other at the start. For performance, rather than loop here,
1485 * we output one chunk, see if there's another one, and if so, output
1486 * it too.
1487 */
1488
1489 n = ndqb(&tp->t_outq, 0);
1490 buf = tp->t_outq.c_cf;
1491
1492 if (!(scr->scr_flags & SCR_GRAPHICS4)) {
1493#ifdef HAVE_BURNER_SUPPORT
1494 wsdisplay_burn(sc, WSDISPLAY_BURN_OUTPUT0x0008);
1495#endif
1496#ifdef HAVE_WSMOUSED_SUPPORT
1497 if (scr == sc->sc_focus)
1498 mouse_remove(scr);
1499#endif
1500 done = (*scr->scr_dconf->wsemul->output)
1501 (scr->scr_dconf->wsemulcookie, buf, n, 0);
1502 } else
1503 done = n;
1504 ndflush(&tp->t_outq, done);
1505
1506 if (done == n) {
1507 if ((n = ndqb(&tp->t_outq, 0)) > 0) {
1508 buf = tp->t_outq.c_cf;
1509
1510 if (!(scr->scr_flags & SCR_GRAPHICS4)) {
1511 done = (*scr->scr_dconf->wsemul->output)
1512 (scr->scr_dconf->wsemulcookie, buf, n, 0);
1513 } else
1514 done = n;
1515 ndflush(&tp->t_outq, done);
1516 }
1517 }
1518
1519 s = spltty()splraise(0x9);
1520 tp->t_state &= ~TS_BUSY0x00004;
1521 /* Come back if there's more to do */
1522 if (tp->t_outq.c_cc) {
1523 tp->t_state |= TS_TIMEOUT0x00080;
1524 timeout_add(&tp->t_rstrt_to, (hz > 128) ? (hz / 128) : 1);
1525 }
1526low:
1527 ttwakeupwr(tp);
1528 splx(s)spllower(s);
1529}
1530
1531int
1532wsdisplaystop(struct tty *tp, int flag)
1533{
1534 int s;
1535
1536 s = spltty()splraise(0x9);
1537 if (ISSET(tp->t_state, TS_BUSY)((tp->t_state) & (0x00004)))
1538 if (!ISSET(tp->t_state, TS_TTSTOP)((tp->t_state) & (0x00100)))
1539 SET(tp->t_state, TS_FLUSH)((tp->t_state) |= (0x00010));
1540 splx(s)spllower(s);
1541
1542 return (0);
1543}
1544
1545/* Set line parameters. */
1546int
1547wsdisplayparam(struct tty *tp, struct termios *t)
1548{
1549
1550 tp->t_ispeedt_termios.c_ispeed = t->c_ispeed;
1551 tp->t_ospeedt_termios.c_ospeed = t->c_ospeed;
1552 tp->t_cflagt_termios.c_cflag = t->c_cflag;
1553 return (0);
1554}
1555
1556/*
1557 * Callbacks for the emulation code.
1558 */
1559void
1560wsdisplay_emulbell(void *v)
1561{
1562 struct wsscreen *scr = v;
1563
1564 if (scr == NULL((void *)0)) /* console, before real attach */
1565 return;
1566
1567 if (scr->scr_flags & SCR_GRAPHICS4) /* can this happen? */
1568 return;
1569
1570 (void) wsdisplay_internal_ioctl(scr->sc, scr, WSKBDIO_BELL((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('W')) << 8) | ((1)))
, NULL((void *)0),
1571 FWRITE0x0002, NULL((void *)0));
1572}
1573
1574#if !defined(WSEMUL_NO_VT100)
1575void
1576wsdisplay_emulinput(void *v, const u_char *data, u_int count)
1577{
1578 struct wsscreen *scr = v;
1579 struct tty *tp;
1580
1581 if (v == NULL((void *)0)) /* console, before real attach */
1582 return;
1583
1584 if (scr->scr_flags & SCR_GRAPHICS4) /* XXX can't happen */
1585 return;
1586 if (!WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0)))
1587 return;
1588
1589 tp = scr->scr_tty;
1590 while (count-- > 0)
1591 (*linesw[tp->t_line].l_rint)(*data++, tp);
1592}
1593#endif
1594
1595/*
1596 * Calls from the keyboard interface.
1597 */
1598void
1599wsdisplay_kbdinput(struct device *dev, kbd_t layout, keysym_t *ks, int num)
1600{
1601 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
1602 struct wsscreen *scr;
1603 const u_char *dp;
1604 int count;
1605 struct tty *tp;
1606
1607 scr = sc->sc_focus;
1608 if (!scr || !WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0)))
1609 return;
1610
1611
1612 tp = scr->scr_tty;
1613 for (; num > 0; num--) {
1614 count = (*scr->scr_dconf->wsemul->translate)
1615 (scr->scr_dconf->wsemulcookie, layout, *ks++, &dp);
1616 while (count-- > 0)
1617 (*linesw[tp->t_line].l_rint)(*dp++, tp);
1618 }
1619}
1620
1621#ifdef WSDISPLAY_COMPAT_RAWKBD1
1622void
1623wsdisplay_rawkbdinput(struct device *dev, u_char *buf, int num)
1624{
1625 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
1626 struct wsscreen *scr;
1627 struct tty *tp;
1628
1629 scr = sc->sc_focus;
1630 if (!scr || !WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0)))
1631 return;
1632
1633 tp = scr->scr_tty;
1634 while (num-- > 0)
1635 (*linesw[tp->t_line].l_rint)(*buf++, tp);
1636}
1637int
1638wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr)
1639{
1640#if NWSKBD1 > 0
1641 int s, raw, data, error;
1642 struct wsevsrc *inp;
1643
1644 s = spltty()splraise(0x9);
1645
1646 raw = (scr ? scr->scr_rawkbd : 0);
1647
1648 if (scr != sc->sc_focus || sc->sc_rawkbd == raw) {
1649 splx(s)spllower(s);
1650 return (0);
1651 }
1652
1653 data = raw ? WSKBD_RAW1 : WSKBD_TRANSLATED0;
1654 inp = sc->sc_input;
1655 if (inp == NULL((void *)0)) {
1656 splx(s)spllower(s);
1657 return (ENXIO6);
1658 }
1659 error = wsevsrc_display_ioctl(inp, WSKBDIO_SETMODE, &data, FWRITE, 0)((inp)->me_ops->ddispioctl(&(inp)->me_dv, ((unsigned
long)0x80000000 | ((sizeof(int) & 0x1fff) << 16) |
((('W')) << 8) | ((19))), (caddr_t)&data, 0x0002, 0
))
;
1660 if (!error)
1661 sc->sc_rawkbd = raw;
1662 splx(s)spllower(s);
1663 return (error);
1664#else
1665 return (0);
1666#endif
1667}
1668#endif
1669
1670int
1671wsdisplay_switch3(void *arg, int error, int waitok)
1672{
1673 struct wsdisplay_softc *sc = arg;
1674 int no;
1675 struct wsscreen *scr;
1676
1677#ifdef WSDISPLAY_COMPAT_USL1
1678 if (!ISSET(sc->sc_flags, SC_SWITCHPENDING)((sc->sc_flags) & (0x01))) {
1679 printf("wsdisplay_switch3: not switching\n");
1680 return (EINVAL22);
1681 }
1682
1683 no = sc->sc_screenwanted;
1684 if (no < 0 || no >= WSDISPLAY_MAXSCREEN12)
1685 panic("wsdisplay_switch3: invalid screen %d", no);
1686 scr = sc->sc_scr[no];
1687 if (!scr) {
1688 printf("wsdisplay_switch3: screen %d disappeared\n", no);
1689 error = ENXIO6;
1690 }
1691
1692 if (error) {
1693 /* try to recover, avoid recursion */
1694
1695 if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN-1) {
1696 printf("wsdisplay_switch3: giving up\n");
1697 sc->sc_focus = NULL((void *)0);
1698#ifdef WSDISPLAY_COMPAT_RAWKBD1
1699 wsdisplay_update_rawkbd(sc, 0);
1700#endif
1701 CLR(sc->sc_flags, SC_SWITCHPENDING)((sc->sc_flags) &= ~(0x01));
1702 return (error);
1703 }
1704
1705 sc->sc_screenwanted = sc->sc_oldscreen;
1706 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN-1;
1707 return (wsdisplay_switch1(arg, 0, waitok));
1708 }
1709#else
1710 /*
1711 * If we do not have syncops support, we come straight from
1712 * wsdisplay_switch2 which has already validated our arguments
1713 * and did not sleep.
1714 */
1715 no = sc->sc_screenwanted;
1716 scr = sc->sc_scr[no];
1717#endif
1718
1719 CLR(sc->sc_flags, SC_SWITCHPENDING)((sc->sc_flags) &= ~(0x01));
1720
1721#ifdef HAVE_BURNER_SUPPORT
1722 if (!error)
1723 wsdisplay_burner_setup(sc, scr);
1724#endif
1725
1726 if (!error && (scr->scr_flags & SCR_WAITACTIVE2))
1727 wakeup(scr);
1728 return (error);
1729}
1730
1731int
1732wsdisplay_switch2(void *arg, int error, int waitok)
1733{
1734 struct wsdisplay_softc *sc = arg;
1735 int no;
1736 struct wsscreen *scr;
1737
1738 if (!ISSET(sc->sc_flags, SC_SWITCHPENDING)((sc->sc_flags) & (0x01))) {
1739 printf("wsdisplay_switch2: not switching\n");
1740 return (EINVAL22);
1741 }
1742
1743 no = sc->sc_screenwanted;
1744 if (no < 0 || no >= WSDISPLAY_MAXSCREEN12)
1745 panic("wsdisplay_switch2: invalid screen %d", no);
1746 scr = sc->sc_scr[no];
1747 if (!scr) {
1748 printf("wsdisplay_switch2: screen %d disappeared\n", no);
1749 error = ENXIO6;
1750 }
1751
1752 if (error) {
1753 /* try to recover, avoid recursion */
1754
1755 if (sc->sc_oldscreen == WSDISPLAY_NULLSCREEN-1) {
1756 printf("wsdisplay_switch2: giving up\n");
1757 sc->sc_focus = NULL((void *)0);
1758 CLR(sc->sc_flags, SC_SWITCHPENDING)((sc->sc_flags) &= ~(0x01));
1759 return (error);
1760 }
1761
1762 sc->sc_screenwanted = sc->sc_oldscreen;
1763 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN-1;
1764 return (wsdisplay_switch1(arg, 0, waitok));
1765 }
1766
1767 sc->sc_focusidx = no;
1768 sc->sc_focus = scr;
1769
1770#ifdef WSDISPLAY_COMPAT_RAWKBD1
1771 (void) wsdisplay_update_rawkbd(sc, scr);
1772#endif
1773 /* keyboard map??? */
1774
1775#ifdef WSDISPLAY_COMPAT_USL1
1776#define wsswitch_cb3((void (*)(void *, int, int))wsdisplay_switch3) ((void (*)(void *, int, int))wsdisplay_switch3)
1777 if (scr->scr_syncops) {
1778 error = (*scr->scr_syncops->attach)(scr->scr_synccookie, waitok,
1779 sc->sc_isconsole && wsdisplay_cons_pollmode ?
1780 0 : wsswitch_cb3((void (*)(void *, int, int))wsdisplay_switch3), sc);
1781 if (error == EAGAIN35) {
1782 /* switch will be done asynchronously */
1783 return (0);
1784 }
1785 }
1786#endif
1787
1788 return (wsdisplay_switch3(sc, error, waitok));
1789}
1790
1791int
1792wsdisplay_switch1(void *arg, int error, int waitok)
1793{
1794 struct wsdisplay_softc *sc = arg;
1795 int no;
1796 struct wsscreen *scr;
1797
1798 if (!ISSET(sc->sc_flags, SC_SWITCHPENDING)((sc->sc_flags) & (0x01))) {
1799 printf("wsdisplay_switch1: not switching\n");
1800 return (EINVAL22);
1801 }
1802
1803 no = sc->sc_screenwanted;
1804 if (no == WSDISPLAY_NULLSCREEN-1) {
1805 CLR(sc->sc_flags, SC_SWITCHPENDING)((sc->sc_flags) &= ~(0x01));
1806 if (!error) {
1807 sc->sc_focus = NULL((void *)0);
1808 }
1809 wakeup(sc);
1810 return (error);
1811 }
1812 if (no < 0 || no >= WSDISPLAY_MAXSCREEN12)
1813 panic("wsdisplay_switch1: invalid screen %d", no);
1814 scr = sc->sc_scr[no];
1815 if (!scr) {
1816 printf("wsdisplay_switch1: screen %d disappeared\n", no);
1817 error = ENXIO6;
1818 }
1819
1820 if (error) {
1821 CLR(sc->sc_flags, SC_SWITCHPENDING)((sc->sc_flags) &= ~(0x01));
1822 return (error);
1823 }
1824
1825#define wsswitch_cb2((void (*)(void *, int, int))wsdisplay_switch2) ((void (*)(void *, int, int))wsdisplay_switch2)
1826 error = (*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
1827 scr->scr_dconf->emulcookie, waitok,
1828 sc->sc_isconsole && wsdisplay_cons_pollmode ? 0 : wsswitch_cb2((void (*)(void *, int, int))wsdisplay_switch2), sc);
1829 if (error == EAGAIN35) {
1830 /* switch will be done asynchronously */
1831 return (0);
1832 }
1833
1834 return (wsdisplay_switch2(sc, error, waitok));
1835}
1836
1837int
1838wsdisplay_switch(struct device *dev, int no, int waitok)
1839{
1840 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
1841 int s, res = 0;
1842 struct wsscreen *scr;
1843
1844 if (no != WSDISPLAY_NULLSCREEN-1) {
1845 if (no < 0 || no >= WSDISPLAY_MAXSCREEN12)
1846 return (EINVAL22);
1847 if (sc->sc_scr[no] == NULL((void *)0))
1848 return (ENXIO6);
1849 }
1850
1851 s = spltty()splraise(0x9);
1852
1853 while (sc->sc_resumescreen != WSDISPLAY_NULLSCREEN-1 && res == 0)
1854 res = tsleep_nsec(&sc->sc_resumescreen, PCATCH0x100, "wsrestore",
1855 INFSLP0xffffffffffffffffULL);
1856 if (res) {
1857 splx(s)spllower(s);
1858 return (res);
1859 }
1860
1861 if ((sc->sc_focus && no == sc->sc_focusidx) ||
1862 (sc->sc_focus == NULL((void *)0) && no == WSDISPLAY_NULLSCREEN-1)) {
1863 splx(s)spllower(s);
1864 return (0);
1865 }
1866
1867 if (ISSET(sc->sc_flags, SC_SWITCHPENDING)((sc->sc_flags) & (0x01))) {
1868 splx(s)spllower(s);
1869 return (EBUSY16);
1870 }
1871
1872 SET(sc->sc_flags, SC_SWITCHPENDING)((sc->sc_flags) |= (0x01));
1873 sc->sc_screenwanted = no;
1874
1875 splx(s)spllower(s);
1876
1877 scr = sc->sc_focus;
1878 if (!scr) {
1879 sc->sc_oldscreen = WSDISPLAY_NULLSCREEN-1;
1880 return (wsdisplay_switch1(sc, 0, waitok));
1881 } else
1882 sc->sc_oldscreen = sc->sc_focusidx;
1883
1884#ifdef WSDISPLAY_COMPAT_USL1
1885#define wsswitch_cb1((void (*)(void *, int, int))wsdisplay_switch1) ((void (*)(void *, int, int))wsdisplay_switch1)
1886 if (scr->scr_syncops) {
1887 res = (*scr->scr_syncops->detach)(scr->scr_synccookie, waitok,
1888 sc->sc_isconsole && wsdisplay_cons_pollmode ?
1889 0 : wsswitch_cb1((void (*)(void *, int, int))wsdisplay_switch1), sc);
1890 if (res == EAGAIN35) {
1891 /* switch will be done asynchronously */
1892 return (0);
1893 }
1894 } else if (scr->scr_flags & SCR_GRAPHICS4) {
1895 /* no way to save state */
1896 res = EBUSY16;
1897 }
1898#endif
1899
1900#ifdef HAVE_WSMOUSED_SUPPORT
1901 mouse_remove(scr);
1902#endif
1903
1904 return (wsdisplay_switch1(sc, res, waitok));
1905}
1906
1907void
1908wsdisplay_reset(struct device *dev, enum wsdisplay_resetops op)
1909{
1910 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
1911 struct wsscreen *scr;
1912
1913 scr = sc->sc_focus;
1914
1915 if (!scr)
1916 return;
1917
1918 switch (op) {
1919 case WSDISPLAY_RESETEMUL:
1920 (*scr->scr_dconf->wsemul->reset)(scr->scr_dconf->wsemulcookie,
1921 WSEMUL_RESET);
1922 break;
1923 case WSDISPLAY_RESETCLOSE:
1924 wsdisplay_closescreen(sc, scr);
1925 break;
1926 }
1927}
1928
1929#ifdef WSDISPLAY_COMPAT_USL1
1930/*
1931 * Interface for (external) VT switch / process synchronization code
1932 */
1933int
1934wsscreen_attach_sync(struct wsscreen *scr, const struct wscons_syncops *ops,
1935 void *cookie)
1936{
1937 if (scr->scr_syncops) {
1938 /*
1939 * The screen is already claimed.
1940 * Check if the owner is still alive.
1941 */
1942 if ((*scr->scr_syncops->check)(scr->scr_synccookie))
1943 return (EBUSY16);
1944 }
1945 scr->scr_syncops = ops;
1946 scr->scr_synccookie = cookie;
1947 return (0);
1948}
1949
1950int
1951wsscreen_detach_sync(struct wsscreen *scr)
1952{
1953 if (!scr->scr_syncops)
1954 return (EINVAL22);
1955 scr->scr_syncops = NULL((void *)0);
1956 return (0);
1957}
1958
1959int
1960wsscreen_lookup_sync(struct wsscreen *scr,
1961 const struct wscons_syncops *ops, /* used as ID */
1962 void **cookiep)
1963{
1964 if (!scr->scr_syncops || ops != scr->scr_syncops)
1965 return (EINVAL22);
1966 *cookiep = scr->scr_synccookie;
1967 return (0);
1968}
1969#endif
1970
1971/*
1972 * Interface to virtual screen stuff
1973 */
1974int
1975wsdisplay_maxscreenidx(struct wsdisplay_softc *sc)
1976{
1977 return (WSDISPLAY_MAXSCREEN12 - 1);
1978}
1979
1980int
1981wsdisplay_screenstate(struct wsdisplay_softc *sc, int idx)
1982{
1983 if (idx < 0 || idx >= WSDISPLAY_MAXSCREEN12)
1984 return (EINVAL22);
1985 if (!sc->sc_scr[idx])
1986 return (ENXIO6);
1987 return ((sc->sc_scr[idx]->scr_flags & SCR_OPEN1) ? EBUSY16 : 0);
1988}
1989
1990int
1991wsdisplay_getactivescreen(struct wsdisplay_softc *sc)
1992{
1993 return (sc->sc_focus ? sc->sc_focusidx : WSDISPLAY_NULLSCREEN-1);
1994}
1995
1996int
1997wsscreen_switchwait(struct wsdisplay_softc *sc, int no)
1998{
1999 struct wsscreen *scr;
2000 int s, res = 0;
2001
2002 if (no == WSDISPLAY_NULLSCREEN-1) {
2003 s = spltty()splraise(0x9);
2004 while (sc->sc_focus && res == 0) {
2005 res = tsleep_nsec(sc, PCATCH0x100, "wswait", INFSLP0xffffffffffffffffULL);
2006 }
2007 splx(s)spllower(s);
2008 return (res);
2009 }
2010
2011 if (no < 0 || no >= WSDISPLAY_MAXSCREEN12)
2012 return (ENXIO6);
2013 scr = sc->sc_scr[no];
2014 if (!scr)
2015 return (ENXIO6);
2016
2017 s = spltty()splraise(0x9);
2018 if (scr != sc->sc_focus) {
2019 scr->scr_flags |= SCR_WAITACTIVE2;
2020 res = tsleep_nsec(scr, PCATCH0x100, "wswait2", INFSLP0xffffffffffffffffULL);
2021 if (scr != sc->sc_scr[no])
2022 res = ENXIO6; /* disappeared in the meantime */
2023 else
2024 scr->scr_flags &= ~SCR_WAITACTIVE2;
2025 }
2026 splx(s)spllower(s);
2027 return (res);
2028}
2029
2030void
2031wsdisplay_kbdholdscr(struct wsscreen *scr, int hold)
2032{
2033 if (hold)
2034 scr->scr_hold_screen = 1;
2035 else {
2036 scr->scr_hold_screen = 0;
2037 timeout_add(&scr->scr_tty->t_rstrt_to, 0); /* "immediate" */
2038 }
2039}
2040
2041void
2042wsdisplay_kbdholdscreen(struct device *dev, int hold)
2043{
2044 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
2045 struct wsscreen *scr;
2046
2047 scr = sc->sc_focus;
2048 if (scr != NULL((void *)0) && WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0)))
2049 wsdisplay_kbdholdscr(scr, hold);
2050}
2051
2052#if NWSKBD1 > 0
2053void
2054wsdisplay_set_console_kbd(struct wsevsrc *src)
2055{
2056 if (wsdisplay_console_device == NULL((void *)0)) {
2057 src->me_dispdv = NULL((void *)0);
2058 return;
2059 }
2060#if NWSMUX1 > 0
2061 if (wsmux_attach_sc((struct wsmux_softc *)
2062 wsdisplay_console_device->sc_input, src)) {
2063 src->me_dispdv = NULL((void *)0);
2064 return;
2065 }
2066#else
2067 wsdisplay_console_device->sc_input = src;
2068#endif
2069 src->me_dispdv = &wsdisplay_console_device->sc_dv;
2070}
2071
2072#if NWSMUX1 == 0
2073int
2074wsdisplay_set_kbd(struct device *disp, struct wsevsrc *kbd)
2075{
2076 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)disp;
2077
2078 if (sc->sc_input != NULL((void *)0))
2079 return (EBUSY16);
2080
2081 sc->sc_input = kbd;
2082
2083 return (0);
2084}
2085#endif
2086
2087#endif /* NWSKBD > 0 */
2088
2089/*
2090 * Console interface.
2091 */
2092void
2093wsdisplay_cnputc(dev_t dev, int i)
2094{
2095 struct wsscreen_internal *dc;
2096 char c = i;
2097
2098 if (!wsdisplay_console_initted)
2099 return;
2100
2101 if (wsdisplay_console_device != NULL((void *)0) &&
2102 (wsdisplay_console_device->sc_scr[0] != NULL((void *)0)) &&
2103 (wsdisplay_console_device->sc_scr[0]->scr_flags & SCR_GRAPHICS4))
2104 return;
2105
2106 dc = &wsdisplay_console_conf;
2107#ifdef HAVE_BURNER_SUPPORT
2108 /*wsdisplay_burn(wsdisplay_console_device, WSDISPLAY_BURN_OUTPUT);*/
2109#endif
2110 (void)(*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1);
2111}
2112
2113int
2114wsdisplay_getc_dummy(dev_t dev)
2115{
2116 /* panic? */
2117 return (0);
2118}
2119
2120void
2121wsdisplay_pollc(dev_t dev, int on)
2122{
2123
2124 wsdisplay_cons_pollmode = on;
2125
2126 /* notify to fb drivers */
2127 if (wsdisplay_console_device != NULL((void *)0) &&
2128 wsdisplay_console_device->sc_accessops->pollc != NULL((void *)0))
2129 (*wsdisplay_console_device->sc_accessops->pollc)
2130 (wsdisplay_console_device->sc_accesscookie, on);
2131
2132 /* notify to kbd drivers */
2133 if (wsdisplay_cons_kbd_pollc)
2134 (*wsdisplay_cons_kbd_pollc)(dev, on);
2135}
2136
2137void
2138wsdisplay_set_cons_kbd(int (*get)(dev_t), void (*poll)(dev_t, int),
2139 void (*bell)(dev_t, u_int, u_int, u_int))
2140{
2141 wsdisplay_cons.cn_getc = get;
2142 wsdisplay_cons.cn_bell = bell;
2143 wsdisplay_cons_kbd_pollc = poll;
2144}
2145
2146void
2147wsdisplay_unset_cons_kbd(void)
2148{
2149 wsdisplay_cons.cn_getc = wsdisplay_getc_dummy;
2150 wsdisplay_cons.cn_bell = NULL((void *)0);
2151 wsdisplay_cons_kbd_pollc = NULL((void *)0);
2152}
2153
2154/*
2155 * Switch the console display to its first screen.
2156 */
2157void
2158wsdisplay_switchtoconsole(void)
2159{
2160 struct wsdisplay_softc *sc;
2161 struct wsscreen *scr;
2162
2163 if (wsdisplay_console_device != NULL((void *)0) && cn_tab == &wsdisplay_cons) {
2164 sc = wsdisplay_console_device;
2165 if ((scr = sc->sc_scr[0]) == NULL((void *)0))
2166 return;
2167 (*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
2168 scr->scr_dconf->emulcookie, 0, NULL((void *)0), NULL((void *)0));
2169 }
2170}
2171
2172/*
2173 * Switch rhe console display to its ddb screen, avoiding locking
2174 * where we can.
2175 */
2176void
2177wsdisplay_enter_ddb(void)
2178{
2179 struct wsdisplay_softc *sc;
2180 struct wsscreen *scr;
2181
2182 if (wsdisplay_console_device != NULL((void *)0) && cn_tab == &wsdisplay_cons) {
2183 sc = wsdisplay_console_device;
2184 if ((scr = sc->sc_scr[0]) == NULL((void *)0))
2185 return;
2186 if (sc->sc_accessops->enter_ddb) {
2187 (*sc->sc_accessops->enter_ddb)(sc->sc_accesscookie,
2188 scr->scr_dconf->emulcookie);
2189 } else {
2190 (*sc->sc_accessops->show_screen)(sc->sc_accesscookie,
2191 scr->scr_dconf->emulcookie, 0, NULL((void *)0), NULL((void *)0));
2192 }
2193 }
2194}
2195
2196/*
2197 * Deal with the xserver doing driver in userland and thus screwing up suspend
2198 * and resume by switching away from it at suspend/resume time.
2199 *
2200 * these functions must be called from the MD suspend callback, since we may
2201 * need to sleep if we have a user (probably an X server) on a vt. therefore
2202 * this can't be a config_suspend() hook.
2203 */
2204void
2205wsdisplay_suspend(void)
2206{
2207 int i;
2208
2209 for (i = 0; i < wsdisplay_cd.cd_ndevs; i++)
2210 if (wsdisplay_cd.cd_devs[i] != NULL((void *)0))
2211 wsdisplay_suspend_device(wsdisplay_cd.cd_devs[i]);
2212}
2213
2214void
2215wsdisplay_suspend_device(struct device *dev)
2216{
2217 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
2218 struct wsscreen *scr;
2219 int active, idx, ret = 0, s;
2220
2221 if ((active = wsdisplay_getactivescreen(sc)) == WSDISPLAY_NULLSCREEN-1)
2222 return;
2223
2224 scr = sc->sc_scr[active];
2225 /*
2226 * We want to switch out of graphics mode for the suspend, but
2227 * only if we're in WSDISPLAY_MODE_MAPPED.
2228 */
2229retry:
2230 idx = WSDISPLAY_MAXSCREEN12;
2231 if (scr->scr_flags & SCR_GRAPHICS4 &&
2232 (scr->scr_flags & SCR_DUMBFB8) == 0) {
2233 for (idx = 0; idx < WSDISPLAY_MAXSCREEN12; idx++) {
2234 if (sc->sc_scr[idx] == NULL((void *)0) || sc->sc_scr[idx] == scr)
2235 continue;
2236
2237 if ((sc->sc_scr[idx]->scr_flags & SCR_GRAPHICS4) == 0)
2238 break;
2239 }
2240 }
2241
2242 /* if we don't have anything to switch to, we can't do anything */
2243 if (idx == WSDISPLAY_MAXSCREEN12)
2244 return;
2245
2246 /*
2247 * we do a lot of magic here because we need to know that the
2248 * switch has completed before we return
2249 */
2250 ret = wsdisplay_switch((struct device *)sc, idx, 1);
2251 if (ret == EBUSY16) {
2252 /* XXX sleep on what's going on */
2253 goto retry;
2254 } else if (ret)
2255 return;
2256
2257 s = spltty()splraise(0x9);
2258 sc->sc_resumescreen = active; /* block other vt switches until resume */
2259 splx(s)spllower(s);
2260 /*
2261 * This will either return ENXIO (invalid (shouldn't happen) or
2262 * wsdisplay disappeared (problem solved)), or EINTR/ERESTART.
2263 * Not much we can do about the latter since we can't return to
2264 * userland.
2265 */
2266 (void)wsscreen_switchwait(sc, idx);
2267}
2268
2269void
2270wsdisplay_resume(void)
2271{
2272 int i;
2273
2274 for (i = 0; i < wsdisplay_cd.cd_ndevs; i++)
2275 if (wsdisplay_cd.cd_devs[i] != NULL((void *)0))
2276 wsdisplay_resume_device(wsdisplay_cd.cd_devs[i]);
2277}
2278
2279void
2280wsdisplay_resume_device(struct device *dev)
2281{
2282 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
2283 int idx, s;
2284
2285 if (sc->sc_resumescreen != WSDISPLAY_NULLSCREEN-1) {
2286 s = spltty()splraise(0x9);
2287 idx = sc->sc_resumescreen;
2288 sc->sc_resumescreen = WSDISPLAY_NULLSCREEN-1;
2289 wakeup(&sc->sc_resumescreen);
2290 splx(s)spllower(s);
2291 (void)wsdisplay_switch((struct device *)sc, idx, 1);
2292 }
2293}
2294
2295#ifdef HAVE_SCROLLBACK_SUPPORT
2296void
2297wsscrollback(void *arg, int op)
2298{
2299 struct wsdisplay_softc *sc = arg;
2300 int lines;
2301
2302 if (sc->sc_focus == NULL((void *)0))
2303 return;
2304
2305 if (op == WSDISPLAY_SCROLL_RESET2)
2306 lines = 0;
2307 else {
2308 lines = sc->sc_focus->scr_dconf->scrdata->nrows - 1;
2309 if (op == WSDISPLAY_SCROLL_BACKWARD0)
2310 lines = -lines;
2311 }
2312
2313 if (sc->sc_accessops->scrollback) {
2314 (*sc->sc_accessops->scrollback)(sc->sc_accesscookie,
2315 sc->sc_focus->scr_dconf->emulcookie, lines);
2316 }
2317}
2318#endif
2319
2320#ifdef HAVE_BURNER_SUPPORT
2321/*
2322 * Update screen burner behaviour after either a screen focus change or
2323 * a screen mode change.
2324 * This is needed to allow X11 to manage screen blanking without any
2325 * interference from the kernel.
2326 */
2327void
2328wsdisplay_burner_setup(struct wsdisplay_softc *sc, struct wsscreen *scr)
2329{
2330 if (scr->scr_flags & SCR_GRAPHICS4) {
2331 /* enable video _immediately_ if it needs to be... */
2332 if (sc->sc_burnman)
2333 wsdisplay_burner(sc);
2334 /* ...and disable the burner while X is running */
2335 if (sc->sc_burnout) {
2336 timeout_del(&sc->sc_burner);
2337 sc->sc_burnout = 0;
2338 }
2339 } else {
2340 /* reenable the burner after exiting from X */
2341 if (!sc->sc_burnman) {
2342 sc->sc_burnout = sc->sc_burnoutintvl;
2343 wsdisplay_burn(sc, sc->sc_burnflags);
2344 }
2345 }
2346}
2347
2348void
2349wsdisplay_burn(void *v, u_int flags)
2350{
2351 struct wsdisplay_softc *sc = v;
2352
2353 if ((flags & sc->sc_burnflags & (WSDISPLAY_BURN_OUTPUT0x0008 |
2354 WSDISPLAY_BURN_KBD0x0002 | WSDISPLAY_BURN_MOUSE0x0004)) &&
2355 sc->sc_accessops->burn_screen) {
2356 if (sc->sc_burnout)
2357 timeout_add_msec(&sc->sc_burner, sc->sc_burnout);
2358 if (sc->sc_burnman)
2359 sc->sc_burnout = 0;
2360 }
2361}
2362
2363void
2364wsdisplay_burner(void *v)
2365{
2366 struct wsdisplay_softc *sc = v;
2367 int s;
2368
2369 if (sc->sc_accessops->burn_screen) {
2370 (*sc->sc_accessops->burn_screen)(sc->sc_accesscookie,
2371 sc->sc_burnman, sc->sc_burnflags);
2372 s = spltty()splraise(0x9);
2373 if (sc->sc_burnman) {
2374 sc->sc_burnout = sc->sc_burnoutintvl;
2375 timeout_add_msec(&sc->sc_burner, sc->sc_burnout);
2376 } else
2377 sc->sc_burnout = sc->sc_burninintvl;
2378 sc->sc_burnman = !sc->sc_burnman;
2379 splx(s)spllower(s);
2380 }
2381}
2382#endif
2383
2384int
2385wsdisplay_get_param(struct wsdisplay_softc *sc, struct wsdisplay_param *dp)
2386{
2387 int error = ENXIO6;
2388 int i;
2389
2390 if (sc != NULL((void *)0))
2391 return wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_GETPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_param) & 0x1fff) << 16) | ((('W')
) << 8) | ((89)))
, dp);
2392
2393 for (i = 0; i < wsdisplay_cd.cd_ndevs; i++) {
2394 sc = wsdisplay_cd.cd_devs[i];
2395 if (sc == NULL((void *)0))
2396 continue;
2397 error = wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_GETPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_param) & 0x1fff) << 16) | ((('W')
) << 8) | ((89)))
, dp);
2398 if (error == 0)
2399 break;
2400 }
2401
2402 if (error && ws_get_param)
2403 error = ws_get_param(dp);
2404
2405 return error;
2406}
2407
2408int
2409wsdisplay_set_param(struct wsdisplay_softc *sc, struct wsdisplay_param *dp)
2410{
2411 int error = ENXIO6;
2412 int i;
2413
2414 if (sc != NULL((void *)0))
2415 return wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_SETPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_param) & 0x1fff) << 16) | ((('W')
) << 8) | ((90)))
, dp);
2416
2417 for (i = 0; i < wsdisplay_cd.cd_ndevs; i++) {
2418 sc = wsdisplay_cd.cd_devs[i];
2419 if (sc == NULL((void *)0))
2420 continue;
2421 error = wsdisplay_param(&sc->sc_dv, WSDISPLAYIO_SETPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct wsdisplay_param) & 0x1fff) << 16) | ((('W')
) << 8) | ((90)))
, dp);
2422 if (error == 0)
2423 break;
2424 }
2425
2426 if (error && ws_set_param)
2427 error = ws_set_param(dp);
2428
2429 return error;
2430}
2431
2432void
2433wsdisplay_brightness_step(struct device *dev, int dir)
2434{
2435 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
2436 struct wsdisplay_param dp;
2437 int delta, new;
2438
2439 dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS2;
2440 if (wsdisplay_get_param(sc, &dp))
2441 return;
2442
2443 /* Use a step size of approximately 5%. */
2444 delta = max(1, ((dp.max - dp.min) * 5) / 100);
2445 new = dp.curval;
2446
2447 if (dir > 0) {
2448 if (delta > dp.max - dp.curval)
2449 new = dp.max;
2450 else
2451 new += delta;
2452 } else if (dir < 0) {
2453 if (delta > dp.curval - dp.min)
2454 new = dp.min;
2455 else
2456 new -= delta;
2457 }
2458
2459 if (dp.curval == new)
2460 return;
2461
2462 dp.curval = new;
2463 wsdisplay_set_param(sc, &dp);
2464}
2465
2466void
2467wsdisplay_brightness_zero(struct device *dev)
2468{
2469 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
2470 struct wsdisplay_param dp;
2471
2472 dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS2;
2473 if (wsdisplay_get_param(sc, &dp))
2474 return;
2475
2476 dp.curval = dp.min;
2477 wsdisplay_set_param(sc, &dp);
2478}
2479
2480void
2481wsdisplay_brightness_cycle(struct device *dev)
2482{
2483 struct wsdisplay_softc *sc = (struct wsdisplay_softc *)dev;
2484 struct wsdisplay_param dp;
2485
2486 dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS2;
2487 if (wsdisplay_get_param(sc, &dp))
2488 return;
2489
2490 if (dp.curval == dp.max)
2491 wsdisplay_brightness_zero(dev);
2492 else
2493 wsdisplay_brightness_step(dev, 1);
2494}
2495
2496#ifdef HAVE_WSMOUSED_SUPPORT
2497/*
2498 * wsmoused(8) support functions
2499 */
2500
2501/*
2502 * Main function, called from wsdisplay_cfg_ioctl.
2503 */
2504int
2505wsmoused(struct wsdisplay_softc *sc, caddr_t data, int flag, struct proc *p)
2506{
2507 struct wscons_event mouse_event = *(struct wscons_event *)data;
2508
2509 if (IS_MOTION_EVENT(mouse_event.type)(((mouse_event.type) == 6) || ((mouse_event.type) == 7) || ((
mouse_event.type) == 10) || ((mouse_event.type) == 16))
) {
2510 if (sc->sc_focus != NULL((void *)0))
2511 motion_event(sc->sc_focus, mouse_event.type,
2512 mouse_event.value);
2513 return 0;
2514 }
2515 if (IS_BUTTON_EVENT(mouse_event.type)(((mouse_event.type) == 4) || ((mouse_event.type) == 5))) {
2516 if (sc->sc_focus != NULL((void *)0)) {
2517 /* XXX tv_sec contains the number of clicks */
2518 if (mouse_event.type ==
2519 WSCONS_EVENT_MOUSE_DOWN5) {
2520 button_event(sc->sc_focus,
2521 mouse_event.value,
2522 mouse_event.time.tv_sec);
2523 } else
2524 button_event(sc->sc_focus,
2525 mouse_event.value, 0);
2526 }
2527 return (0);
2528 }
2529 if (IS_CTRL_EVENT(mouse_event.type)((mouse_event.type == 12) || (mouse_event.type == 13))) {
2530 return ctrl_event(sc, mouse_event.type,
2531 mouse_event.value, p);
2532 }
2533 return -1;
2534}
2535
2536/*
2537 * Mouse motion events
2538 */
2539void
2540motion_event(struct wsscreen *scr, u_int type, int value)
2541{
2542 switch (type) {
2543 case WSCONS_EVENT_MOUSE_DELTA_X6:
2544 mouse_moverel(scr, value, 0);
2545 break;
2546 case WSCONS_EVENT_MOUSE_DELTA_Y7:
2547 mouse_moverel(scr, 0, -value);
2548 break;
2549#ifdef HAVE_SCROLLBACK_SUPPORT
2550 case WSCONS_EVENT_MOUSE_DELTA_Z10:
2551 mouse_zaxis(scr, value);
2552 break;
2553#endif
2554 default:
2555 break;
2556 }
2557}
2558
2559/*
2560 * Button clicks events
2561 */
2562void
2563button_event(struct wsscreen *scr, int button, int clicks)
2564{
2565 switch (button) {
2566 case MOUSE_COPY_BUTTON0:
2567 switch (clicks % 4) {
2568 case 0: /* button is up */
2569 mouse_copy_end(scr);
2570 mouse_copy_selection(scr);
2571 break;
2572 case 1: /* single click */
2573 mouse_copy_start(scr);
2574 mouse_copy_selection(scr);
2575 break;
2576 case 2: /* double click */
2577 mouse_copy_word(scr);
2578 mouse_copy_selection(scr);
2579 break;
2580 case 3: /* triple click */
2581 mouse_copy_line(scr);
2582 mouse_copy_selection(scr);
2583 break;
2584 }
2585 break;
2586 case MOUSE_PASTE_BUTTON1:
2587 if (clicks != 0)
2588 mouse_paste(scr);
2589 break;
2590 case MOUSE_EXTEND_BUTTON2:
2591 if (clicks != 0)
2592 mouse_copy_extend_after(scr);
2593 break;
2594 default:
2595 break;
2596 }
2597}
2598
2599/*
2600 * Control events
2601 */
2602int
2603ctrl_event(struct wsdisplay_softc *sc, u_int type, int value, struct proc *p)
2604{
2605 struct wsscreen *scr;
2606 int i;
2607
2608 switch (type) {
2609 case WSCONS_EVENT_WSMOUSED_OFF13:
2610 CLR(sc->sc_flags, SC_PASTE_AVAIL)((sc->sc_flags) &= ~(0x02));
2611 return (0);
2612 case WSCONS_EVENT_WSMOUSED_ON12:
2613 if (!sc->sc_accessops->getchar)
2614 /* no wsmoused(8) support in the display driver */
2615 return (1);
2616 allocate_copybuffer(sc);
2617 CLR(sc->sc_flags, SC_PASTE_AVAIL)((sc->sc_flags) &= ~(0x02));
2618
2619 for (i = 0 ; i < WSDISPLAY_DEFAULTSCREENS6 ; i++)
2620 if ((scr = sc->sc_scr[i]) != NULL((void *)0)) {
2621 scr->mouse =
2622 (WS_NCOLS(scr)(((scr)->scr_dconf)->scrdata->ncols) * WS_NROWS(scr)(((scr)->scr_dconf)->scrdata->nrows)) / 2;
2623 scr->cursor = scr->mouse;
2624 scr->cpy_start = 0;
2625 scr->cpy_end = 0;
2626 scr->orig_start = 0;
2627 scr->orig_end = 0;
2628 scr->mouse_flags = 0;
2629 }
2630 return (0);
2631 default: /* can't happen, really */
2632 return 0;
2633 }
2634}
2635
2636void
2637mouse_moverel(struct wsscreen *scr, int dx, int dy)
2638{
2639 struct wsscreen_internal *dconf = scr->scr_dconf;
2640 u_int old_mouse = scr->mouse;
2641 int mouse_col = scr->mouse % N_COLS(dconf)((dconf)->scrdata->ncols);
2642 int mouse_row = scr->mouse / N_COLS(dconf)((dconf)->scrdata->ncols);
2643
2644 /* update position */
2645 if (mouse_col + dx >= MAXCOL(dconf)(((dconf)->scrdata->ncols) - 1))
2646 mouse_col = MAXCOL(dconf)(((dconf)->scrdata->ncols) - 1);
2647 else {
2648 if (mouse_col + dx <= 0)
2649 mouse_col = 0;
2650 else
2651 mouse_col += dx;
2652 }
2653 if (mouse_row + dy >= MAXROW(dconf)(((dconf)->scrdata->nrows) - 1))
2654 mouse_row = MAXROW(dconf)(((dconf)->scrdata->nrows) - 1);
2655 else {
2656 if (mouse_row + dy <= 0)
2657 mouse_row = 0;
2658 else
2659 mouse_row += dy;
2660 }
2661 scr->mouse = mouse_row * N_COLS(dconf)((dconf)->scrdata->ncols) + mouse_col;
2662
2663 /* if we have moved */
2664 if (old_mouse != scr->mouse) {
2665 /* XXX unblank screen if display.ms_act */
2666 if (ISSET(scr->mouse_flags, SEL_IN_PROGRESS)((scr->mouse_flags) & (0x04))) {
2667 /* selection in progress */
2668 mouse_copy_extend(scr);
2669 } else {
2670 inverse_char(scr, scr->mouse);
2671 if (ISSET(scr->mouse_flags, MOUSE_VISIBLE)((scr->mouse_flags) & (0x01)))
2672 inverse_char(scr, old_mouse);
2673 else
2674 SET(scr->mouse_flags, MOUSE_VISIBLE)((scr->mouse_flags) |= (0x01));
2675 }
2676 }
2677}
2678
2679void
2680inverse_char(struct wsscreen *scr, u_int pos)
2681{
2682 struct wsscreen_internal *dconf = scr->scr_dconf;
2683 struct wsdisplay_charcell cell;
2684 int fg, bg, ul;
2685 int flags;
2686 int tmp;
2687 uint32_t attr;
2688
2689 GETCHAR(scr, pos, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (pos) / (((scr)->scr_dconf)->scrdata->
ncols), (pos) % (((scr)->scr_dconf)->scrdata->ncols)
, &cell))
;
2690
2691 (*dconf->emulops->unpack_attr)(dconf->emulcookie, cell.attr, &fg,
2692 &bg, &ul);
2693
2694 /*
2695 * Display the mouse cursor as a color inverted cell whenever
2696 * possible. If this is not possible, ask for the video reverse
2697 * attribute.
2698 */
2699 flags = 0;
2700 if (dconf->scrdata->capabilities & WSSCREEN_WSCOLORS1) {
2701 flags |= WSATTR_WSCOLORS16;
2702 tmp = fg;
2703 fg = bg;
2704 bg = tmp;
2705 } else if (dconf->scrdata->capabilities & WSSCREEN_REVERSE2) {
2706 flags |= WSATTR_REVERSE1;
2707 }
2708 if ((*dconf->emulops->pack_attr)(dconf->emulcookie, fg, bg, flags |
2709 (ul ? WSATTR_UNDERLINE8 : 0), &attr) == 0) {
2710 cell.attr = attr;
2711 PUTCHAR(dconf, pos, cell.uc, cell.attr)((*(dconf)->emulops->putchar) ((dconf)->emulcookie, (
(pos) / ((dconf)->scrdata->ncols)), ((pos) % ((dconf)->
scrdata->ncols)), (cell.uc), (cell.attr)))
;
2712 }
2713}
2714
2715void
2716inverse_region(struct wsscreen *scr, u_int start, u_int end)
2717{
2718 struct wsscreen_internal *dconf = scr->scr_dconf;
2719 u_int current_pos;
2720 u_int abs_end;
2721
2722 /* sanity check, useful because 'end' can be (u_int)-1 */
2723 abs_end = N_COLS(dconf)((dconf)->scrdata->ncols) * N_ROWS(dconf)((dconf)->scrdata->nrows);
2724 if (end > abs_end)
2725 return;
2726 current_pos = start;
2727 while (current_pos <= end)
2728 inverse_char(scr, current_pos++);
2729}
2730
2731/*
2732 * Return the number of contiguous blank characters between the right margin
2733 * if border == 1 or between the next non-blank character and the current mouse
2734 * cursor if border == 0
2735 */
2736u_int
2737skip_spc_right(struct wsscreen *scr, int border)
2738{
2739 struct wsscreen_internal *dconf = scr->scr_dconf;
2740 struct wsdisplay_charcell cell;
2741 u_int current = scr->cpy_end;
2742 u_int mouse_col = scr->cpy_end % N_COLS(dconf)((dconf)->scrdata->ncols);
2743 u_int limit = current + (N_COLS(dconf)((dconf)->scrdata->ncols) - mouse_col - 1);
2744 u_int res = 0;
2745
2746 while (GETCHAR(scr, current, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (current) / (((scr)->scr_dconf)->scrdata
->ncols), (current) % (((scr)->scr_dconf)->scrdata->
ncols), &cell))
== 0 && cell.uc == ' ' &&
2747 current <= limit) {
2748 current++;
2749 res++;
2750 }
2751 if (border == BORDER1) {
2752 if (current > limit)
2753 return (res - 1);
2754 else
2755 return (0);
2756 } else {
2757 if (res != 0)
2758 return (res - 1);
2759 else
2760 return (res);
2761 }
2762}
2763
2764/*
2765 * Return the number of contiguous blank characters between the first of the
2766 * contiguous blank characters and the current mouse cursor
2767 */
2768u_int
2769skip_spc_left(struct wsscreen *scr)
2770{
2771 struct wsscreen_internal *dconf = scr->scr_dconf;
2772 struct wsdisplay_charcell cell;
2773 u_int current = scr->cpy_start;
2774 u_int mouse_col = scr->mouse % N_COLS(dconf)((dconf)->scrdata->ncols);
2775 u_int limit = current - mouse_col;
2776 u_int res = 0;
2777
2778 while (GETCHAR(scr, current, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (current) / (((scr)->scr_dconf)->scrdata
->ncols), (current) % (((scr)->scr_dconf)->scrdata->
ncols), &cell))
== 0 && cell.uc == ' ' &&
2779 current >= limit) {
2780 current--;
2781 res++;
2782 }
2783 if (res != 0)
2784 res--;
2785 return (res);
2786}
2787
2788/*
2789 * Class of characters
2790 * Stolen from xterm sources of the Xfree project (see cvs tag below)
2791 * $TOG: button.c /main/76 1997/07/30 16:56:19 kaleb $
2792 */
2793static const int charClass[256] = {
2794/* NUL SOH STX ETX EOT ENQ ACK BEL */
2795 32, 1, 1, 1, 1, 1, 1, 1,
2796/* BS HT NL VT NP CR SO SI */
2797 1, 32, 1, 1, 1, 1, 1, 1,
2798/* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
2799 1, 1, 1, 1, 1, 1, 1, 1,
2800/* CAN EM SUB ESC FS GS RS US */
2801 1, 1, 1, 1, 1, 1, 1, 1,
2802/* SP ! " # $ % & ' */
2803 32, 33, 34, 35, 36, 37, 38, 39,
2804/* ( ) * + , - . / */
2805 40, 41, 42, 43, 44, 45, 46, 47,
2806/* 0 1 2 3 4 5 6 7 */
2807 48, 48, 48, 48, 48, 48, 48, 48,
2808/* 8 9 : ; < = > ? */
2809 48, 48, 58, 59, 60, 61, 62, 63,
2810/* @ A B C D E F G */
2811 64, 48, 48, 48, 48, 48, 48, 48,
2812/* H I J K L M N O */
2813 48, 48, 48, 48, 48, 48, 48, 48,
2814/* P Q R S T U V W */
2815 48, 48, 48, 48, 48, 48, 48, 48,
2816/* X Y Z [ \ ] ^ _ */
2817 48, 48, 48, 91, 92, 93, 94, 48,
2818/* ` a b c d e f g */
2819 96, 48, 48, 48, 48, 48, 48, 48,
2820/* h i j k l m n o */
2821 48, 48, 48, 48, 48, 48, 48, 48,
2822/* p q r s t u v w */
2823 48, 48, 48, 48, 48, 48, 48, 48,
2824/* x y z { | } ~ DEL */
2825 48, 48, 48, 123, 124, 125, 126, 1,
2826/* x80 x81 x82 x83 IND NEL SSA ESA */
2827 1, 1, 1, 1, 1, 1, 1, 1,
2828/* HTS HTJ VTS PLD PLU RI SS2 SS3 */
2829 1, 1, 1, 1, 1, 1, 1, 1,
2830/* DCS PU1 PU2 STS CCH MW SPA EPA */
2831 1, 1, 1, 1, 1, 1, 1, 1,
2832/* x98 x99 x9A CSI ST OSC PM APC */
2833 1, 1, 1, 1, 1, 1, 1, 1,
2834/* - i c/ L ox Y- | So */
2835 160, 161, 162, 163, 164, 165, 166, 167,
2836/* .. c0 ip << _ R0 - */
2837 168, 169, 170, 171, 172, 173, 174, 175,
2838/* o +- 2 3 ' u q| . */
2839 176, 177, 178, 179, 180, 181, 182, 183,
2840/* , 1 2 >> 1/4 1/2 3/4 ? */
2841 184, 185, 186, 187, 188, 189, 190, 191,
2842/* A` A' A^ A~ A: Ao AE C, */
2843 48, 48, 48, 48, 48, 48, 48, 48,
2844/* E` E' E^ E: I` I' I^ I: */
2845 48, 48, 48, 48, 48, 48, 48, 48,
2846/* D- N~ O` O' O^ O~ O: X */
2847 48, 48, 48, 48, 48, 48, 48, 216,
2848/* O/ U` U' U^ U: Y' P B */
2849 48, 48, 48, 48, 48, 48, 48, 48,
2850/* a` a' a^ a~ a: ao ae c, */
2851 48, 48, 48, 48, 48, 48, 48, 48,
2852/* e` e' e^ e: i` i' i^ i: */
2853 48, 48, 48, 48, 48, 48, 48, 48,
2854/* d n~ o` o' o^ o~ o: -: */
2855 48, 48, 48, 48, 48, 48, 48, 248,
2856/* o/ u` u' u^ u: y' P y: */
2857 48, 48, 48, 48, 48, 48, 48, 48
2858};
2859
2860/*
2861 * Find the first blank beginning after the current cursor position
2862 */
2863u_int
2864skip_char_right(struct wsscreen *scr, u_int offset)
2865{
2866 struct wsscreen_internal *dconf = scr->scr_dconf;
2867 struct wsdisplay_charcell cell;
2868 u_int current = offset;
2869 u_int limit = current +
2870 (N_COLS(dconf)((dconf)->scrdata->ncols) - (scr->mouse % N_COLS(dconf)((dconf)->scrdata->ncols)) - 1);
2871 u_int class;
2872 u_int res = 0;
2873
2874 GETCHAR(scr, current, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (current) / (((scr)->scr_dconf)->scrdata
->ncols), (current) % (((scr)->scr_dconf)->scrdata->
ncols), &cell))
;
2875 class = charClass[cell.uc & 0xff];
2876 while (GETCHAR(scr, current, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (current) / (((scr)->scr_dconf)->scrdata
->ncols), (current) % (((scr)->scr_dconf)->scrdata->
ncols), &cell))
== 0 &&
2877 charClass[cell.uc & 0xff] == class && current <= limit) {
2878 current++;
2879 res++;
2880 }
2881 if (res != 0)
2882 res--;
2883 return (res);
2884}
2885
2886/*
2887 * Find the first non-blank character before the cursor position
2888 */
2889u_int
2890skip_char_left(struct wsscreen *scr, u_int offset)
2891{
2892 struct wsscreen_internal *dconf = scr->scr_dconf;
2893 struct wsdisplay_charcell cell;
2894 u_int current = offset;
2895 u_int limit = current - (scr->mouse % N_COLS(dconf)((dconf)->scrdata->ncols));
2896 u_int class;
2897 u_int res = 0;
2898
2899 GETCHAR(scr, current, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (current) / (((scr)->scr_dconf)->scrdata
->ncols), (current) % (((scr)->scr_dconf)->scrdata->
ncols), &cell))
;
2900 class = charClass[cell.uc & 0xff];
2901 while (GETCHAR(scr, current, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (current) / (((scr)->scr_dconf)->scrdata
->ncols), (current) % (((scr)->scr_dconf)->scrdata->
ncols), &cell))
== 0 &&
2902 charClass[cell.uc & 0xff] == class && current >= limit) {
2903 current--;
2904 res++;
2905 }
2906 if (res != 0)
2907 res--;
2908 return (res);
2909}
2910
2911/*
2912 * Compare character classes
2913 */
2914u_int
2915class_cmp(struct wsscreen *scr, u_int first, u_int second)
2916{
2917 struct wsdisplay_charcell cell;
2918 u_int first_class;
2919 u_int second_class;
2920
2921 if (GETCHAR(scr, first, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (first) / (((scr)->scr_dconf)->scrdata
->ncols), (first) % (((scr)->scr_dconf)->scrdata->
ncols), &cell))
!= 0)
2922 return (1);
2923 first_class = charClass[cell.uc & 0xff];
2924 if (GETCHAR(scr, second, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (second) / (((scr)->scr_dconf)->scrdata
->ncols), (second) % (((scr)->scr_dconf)->scrdata->
ncols), &cell))
!= 0)
2925 return (1);
2926 second_class = charClass[cell.uc & 0xff];
2927
2928 if (first_class != second_class)
2929 return (1);
2930 else
2931 return (0);
2932}
2933
2934/*
2935 * Beginning of a copy operation
2936 */
2937void
2938mouse_copy_start(struct wsscreen *scr)
2939{
2940 u_int right;
2941
2942 /* if no selection, then that's the first one */
2943 SET(scr->sc->sc_flags, SC_PASTE_AVAIL)((scr->sc->sc_flags) |= (0x02));
2944
2945 /* remove the previous selection */
2946 if (ISSET(scr->mouse_flags, SEL_EXISTS)((scr->mouse_flags) & (0x02)))
2947 remove_selection(scr);
2948
2949 /* initial show of the cursor */
2950 if (!ISSET(scr->mouse_flags, MOUSE_VISIBLE)((scr->mouse_flags) & (0x01)))
2951 inverse_char(scr, scr->mouse);
2952
2953 scr->cpy_start = scr->cpy_end = scr->mouse;
2954 scr->orig_start = scr->cpy_start;
2955 scr->orig_end = scr->cpy_end;
2956 scr->cursor = scr->cpy_end + 1; /* init value */
2957
2958 /* useful later, in mouse_copy_extend */
2959 right = skip_spc_right(scr, BORDER1);
2960 if (right)
2961 SET(scr->mouse_flags, BLANK_TO_EOL)((scr->mouse_flags) |= (0x10));
2962
2963 SET(scr->mouse_flags, SEL_IN_PROGRESS | SEL_EXISTS | SEL_BY_CHAR)((scr->mouse_flags) |= (0x04 | 0x02 | 0x20));
2964 CLR(scr->mouse_flags, SEL_BY_WORD | SEL_BY_LINE)((scr->mouse_flags) &= ~(0x40 | 0x80));
2965 CLR(scr->mouse_flags, MOUSE_VISIBLE)((scr->mouse_flags) &= ~(0x01)); /* cursor hidden in selection */
2966}
2967
2968/*
2969 * Copy of the word under the cursor
2970 */
2971void
2972mouse_copy_word(struct wsscreen *scr)
2973{
2974 struct wsdisplay_charcell cell;
2975 u_int right;
2976 u_int left;
2977
2978 if (ISSET(scr->mouse_flags, SEL_EXISTS)((scr->mouse_flags) & (0x02)))
2979 remove_selection(scr);
2980
2981 if (ISSET(scr->mouse_flags, MOUSE_VISIBLE)((scr->mouse_flags) & (0x01)))
2982 inverse_char(scr, scr->mouse);
2983
2984 scr->cpy_start = scr->cpy_end = scr->mouse;
2985
2986 if (GETCHAR(scr, scr->mouse, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (scr->mouse) / (((scr)->scr_dconf)->
scrdata->ncols), (scr->mouse) % (((scr)->scr_dconf)->
scrdata->ncols), &cell))
== 0 &&
2987 IS_ALPHANUM(cell.uc)((cell.uc) != ' ')) {
2988 right = skip_char_right(scr, scr->cpy_end);
2989 left = skip_char_left(scr, scr->cpy_start);
2990 } else {
2991 right = skip_spc_right(scr, NO_BORDER0);
2992 left = skip_spc_left(scr);
2993 }
2994
2995 scr->cpy_start -= left;
2996 scr->cpy_end += right;
2997 scr->orig_start = scr->cpy_start;
2998 scr->orig_end = scr->cpy_end;
2999 scr->cursor = scr->cpy_end + 1; /* init value, never happen */
3000 inverse_region(scr, scr->cpy_start, scr->cpy_end);
3001
3002 SET(scr->mouse_flags, SEL_IN_PROGRESS | SEL_EXISTS | SEL_BY_WORD)((scr->mouse_flags) |= (0x04 | 0x02 | 0x40));
3003 CLR(scr->mouse_flags, SEL_BY_CHAR | SEL_BY_LINE)((scr->mouse_flags) &= ~(0x20 | 0x80));
3004 /* mouse cursor hidden in the selection */
3005 CLR(scr->mouse_flags, BLANK_TO_EOL | MOUSE_VISIBLE)((scr->mouse_flags) &= ~(0x10 | 0x01));
3006}
3007
3008/*
3009 * Copy of the current line
3010 */
3011void
3012mouse_copy_line(struct wsscreen *scr)
3013{
3014 struct wsscreen_internal *dconf = scr->scr_dconf;
3015 u_int row = scr->mouse / N_COLS(dconf)((dconf)->scrdata->ncols);
3016
3017 if (ISSET(scr->mouse_flags, SEL_EXISTS)((scr->mouse_flags) & (0x02)))
3018 remove_selection(scr);
3019
3020 if (ISSET(scr->mouse_flags, MOUSE_VISIBLE)((scr->mouse_flags) & (0x01)))
3021 inverse_char(scr, scr->mouse);
3022
3023 scr->cpy_start = row * N_COLS(dconf)((dconf)->scrdata->ncols);
3024 scr->cpy_end = scr->cpy_start + (N_COLS(dconf)((dconf)->scrdata->ncols) - 1);
3025 scr->orig_start = scr->cpy_start;
3026 scr->orig_end = scr->cpy_end;
3027 scr->cursor = scr->cpy_end + 1;
3028 inverse_region(scr, scr->cpy_start, scr->cpy_end);
3029
3030 SET(scr->mouse_flags, SEL_IN_PROGRESS | SEL_EXISTS | SEL_BY_LINE)((scr->mouse_flags) |= (0x04 | 0x02 | 0x80));
3031 CLR(scr->mouse_flags, SEL_BY_CHAR | SEL_BY_WORD)((scr->mouse_flags) &= ~(0x20 | 0x40));
3032 /* mouse cursor hidden in the selection */
3033 CLR(scr->mouse_flags, BLANK_TO_EOL | MOUSE_VISIBLE)((scr->mouse_flags) &= ~(0x10 | 0x01));
3034}
3035
3036/*
3037 * End of a copy operation
3038 */
3039void
3040mouse_copy_end(struct wsscreen *scr)
3041{
3042 CLR(scr->mouse_flags, SEL_IN_PROGRESS)((scr->mouse_flags) &= ~(0x04));
3043 if (ISSET(scr->mouse_flags, SEL_BY_WORD)((scr->mouse_flags) & (0x40)) ||
3044 ISSET(scr->mouse_flags, SEL_BY_LINE)((scr->mouse_flags) & (0x80))) {
3045 if (scr->cursor != scr->cpy_end + 1)
3046 inverse_char(scr, scr->cursor);
3047 scr->cursor = scr->cpy_end + 1;
3048 }
3049}
3050
3051
3052/*
3053 * Generic selection extend function
3054 */
3055void
3056mouse_copy_extend(struct wsscreen *scr)
3057{
3058 if (ISSET(scr->mouse_flags, SEL_BY_CHAR)((scr->mouse_flags) & (0x20)))
3059 mouse_copy_extend_char(scr);
3060 if (ISSET(scr->mouse_flags, SEL_BY_WORD)((scr->mouse_flags) & (0x40)))
3061 mouse_copy_extend_word(scr);
3062 if (ISSET(scr->mouse_flags, SEL_BY_LINE)((scr->mouse_flags) & (0x80)))
3063 mouse_copy_extend_line(scr);
3064}
3065
3066/*
3067 * Extend a selected region, character by character
3068 */
3069void
3070mouse_copy_extend_char(struct wsscreen *scr)
3071{
3072 u_int right;
3073
3074 if (!ISSET(scr->mouse_flags, SEL_EXT_AFTER)((scr->mouse_flags) & (0x08))) {
3075 if (ISSET(scr->mouse_flags, BLANK_TO_EOL)((scr->mouse_flags) & (0x10))) {
3076 /*
3077 * First extension of selection. We handle special
3078 * cases of blank characters to eol
3079 */
3080
3081 right = skip_spc_right(scr, BORDER1);
3082 if (scr->mouse > scr->orig_start) {
3083 /* the selection goes to the lower part of
3084 the screen */
3085
3086 /* remove the previous cursor, start of
3087 selection is now next line */
3088 inverse_char(scr, scr->cpy_start);
3089 scr->cpy_start += (right + 1);
3090 scr->cpy_end = scr->cpy_start;
3091 scr->orig_start = scr->cpy_start;
3092 /* simulate the initial mark */
3093 inverse_char(scr, scr->cpy_start);
3094 } else {
3095 /* the selection goes to the upper part
3096 of the screen */
3097 /* remove the previous cursor, start of
3098 selection is now at the eol */
3099 inverse_char(scr, scr->cpy_start);
3100 scr->orig_start += (right + 1);
3101 scr->cpy_start = scr->orig_start - 1;
3102 scr->cpy_end = scr->orig_start - 1;
3103 /* simulate the initial mark */
3104 inverse_char(scr, scr->cpy_start);
3105 }
3106 CLR(scr->mouse_flags, BLANK_TO_EOL)((scr->mouse_flags) &= ~(0x10));
3107 }
3108
3109 if (scr->mouse < scr->orig_start &&
3110 scr->cpy_end >= scr->orig_start) {
3111 /* we go to the upper part of the screen */
3112
3113 /* reverse the old selection region */
3114 remove_selection(scr);
3115 scr->cpy_end = scr->orig_start - 1;
3116 scr->cpy_start = scr->orig_start;
3117 }
3118 if (scr->cpy_start < scr->orig_start &&
3119 scr->mouse >= scr->orig_start) {
3120 /* we go to the lower part of the screen */
3121
3122 /* reverse the old selection region */
3123
3124 remove_selection(scr);
3125 scr->cpy_start = scr->orig_start;
3126 scr->cpy_end = scr->orig_start - 1;
3127 }
3128 /* restore flags cleared in remove_selection() */
3129 SET(scr->mouse_flags, SEL_IN_PROGRESS | SEL_EXISTS)((scr->mouse_flags) |= (0x04 | 0x02));
3130 }
3131
3132 if (scr->mouse >= scr->orig_start) {
3133 /* lower part of the screen */
3134 if (scr->mouse > scr->cpy_end) {
3135 /* extending selection */
3136 inverse_region(scr, scr->cpy_end + 1, scr->mouse);
3137 } else {
3138 /* reducing selection */
3139 inverse_region(scr, scr->mouse + 1, scr->cpy_end);
3140 }
3141 scr->cpy_end = scr->mouse;
3142 } else {
3143 /* upper part of the screen */
3144 if (scr->mouse < scr->cpy_start) {
3145 /* extending selection */
3146 inverse_region(scr, scr->mouse, scr->cpy_start - 1);
3147 } else {
3148 /* reducing selection */
3149 inverse_region(scr, scr->cpy_start, scr->mouse - 1);
3150 }
3151 scr->cpy_start = scr->mouse;
3152 }
3153}
3154
3155/*
3156 * Extend a selected region, word by word
3157 */
3158void
3159mouse_copy_extend_word(struct wsscreen *scr)
3160{
3161 u_int old_cpy_end;
3162 u_int old_cpy_start;
3163
3164 if (!ISSET(scr->mouse_flags, SEL_EXT_AFTER)((scr->mouse_flags) & (0x08))) {
3165 /* remove cursor in selection (black one) */
3166 if (scr->cursor != scr->cpy_end + 1)
3167 inverse_char(scr, scr->cursor);
3168
3169 /* now, switch between lower and upper part of the screen */
3170 if (scr->mouse < scr->orig_start &&
3171 scr->cpy_end >= scr->orig_start) {
3172 /* going to the upper part of the screen */
3173 inverse_region(scr, scr->orig_end + 1, scr->cpy_end);
3174 scr->cpy_end = scr->orig_end;
3175 }
3176
3177 if (scr->mouse > scr->orig_end &&
3178 scr->cpy_start <= scr->orig_start) {
3179 /* going to the lower part of the screen */
3180 inverse_region(scr, scr->cpy_start,
3181 scr->orig_start - 1);
3182 scr->cpy_start = scr->orig_start;
3183 }
3184 }
3185
3186 if (scr->mouse >= scr->orig_start) {
3187 /* lower part of the screen */
3188 if (scr->mouse > scr->cpy_end) {
3189 /* extending selection */
3190 old_cpy_end = scr->cpy_end;
3191 scr->cpy_end = scr->mouse +
3192 skip_char_right(scr, scr->mouse);
3193 inverse_region(scr, old_cpy_end + 1, scr->cpy_end);
3194 } else {
3195 if (class_cmp(scr, scr->mouse, scr->mouse + 1)) {
3196 /* reducing selection (remove last word) */
3197 old_cpy_end = scr->cpy_end;
3198 scr->cpy_end = scr->mouse;
3199 inverse_region(scr, scr->cpy_end + 1,
3200 old_cpy_end);
3201 } else {
3202 old_cpy_end = scr->cpy_end;
3203 scr->cpy_end = scr->mouse +
3204 skip_char_right(scr, scr->mouse);
3205 if (scr->cpy_end != old_cpy_end) {
3206 /* reducing selection, from the end of
3207 * next word */
3208 inverse_region(scr, scr->cpy_end + 1,
3209 old_cpy_end);
3210 }
3211 }
3212 }
3213 } else {
3214 /* upper part of the screen */
3215 if (scr->mouse < scr->cpy_start) {
3216 /* extending selection */
3217 old_cpy_start = scr->cpy_start;
3218 scr->cpy_start = scr->mouse -
3219 skip_char_left(scr, scr->mouse);
3220 inverse_region(scr, scr->cpy_start, old_cpy_start - 1);
3221 } else {
3222 if (class_cmp(scr, scr->mouse - 1, scr->mouse)) {
3223 /* reducing selection (remove last word) */
3224 old_cpy_start = scr->cpy_start;
3225 scr->cpy_start = scr->mouse;
3226 inverse_region(scr, old_cpy_start,
3227 scr->cpy_start - 1);
3228 } else {
3229 old_cpy_start = scr->cpy_start;
3230 scr->cpy_start = scr->mouse -
3231 skip_char_left(scr, scr->mouse);
3232 if (scr->cpy_start != old_cpy_start) {
3233 inverse_region(scr, old_cpy_start,
3234 scr->cpy_start - 1);
3235 }
3236 }
3237 }
3238 }
3239
3240 if (!ISSET(scr->mouse_flags, SEL_EXT_AFTER)((scr->mouse_flags) & (0x08))) {
3241 /* display new cursor */
3242 scr->cursor = scr->mouse;
3243 inverse_char(scr, scr->cursor);
3244 }
3245}
3246
3247/*
3248 * Extend a selected region, line by line
3249 */
3250void
3251mouse_copy_extend_line(struct wsscreen *scr)
3252{
3253 struct wsscreen_internal *dconf = scr->scr_dconf;
3254 u_int old_row;
3255 u_int new_row;
3256 u_int old_cpy_start;
3257 u_int old_cpy_end;
3258
3259 if (!ISSET(scr->mouse_flags, SEL_EXT_AFTER)((scr->mouse_flags) & (0x08))) {
3260 /* remove cursor in selection (black one) */
3261 if (scr->cursor != scr->cpy_end + 1)
3262 inverse_char(scr, scr->cursor);
3263
3264 /* now, switch between lower and upper part of the screen */
3265 if (scr->mouse < scr->orig_start &&
3266 scr->cpy_end >= scr->orig_start) {
3267 /* going to the upper part of the screen */
3268 inverse_region(scr, scr->orig_end + 1, scr->cpy_end);
3269 scr->cpy_end = scr->orig_end;
3270 }
3271
3272 if (scr->mouse > scr->orig_end &&
3273 scr->cpy_start <= scr->orig_start) {
3274 /* going to the lower part of the screen */
3275 inverse_region(scr, scr->cpy_start,
3276 scr->orig_start - 1);
3277 scr->cpy_start = scr->orig_start;
3278 }
3279 }
3280
3281 if (scr->mouse >= scr->orig_start) {
3282 /* lower part of the screen */
3283 if (scr->cursor == scr->cpy_end + 1)
3284 scr->cursor = scr->cpy_end;
3285 old_row = scr->cursor / N_COLS(dconf)((dconf)->scrdata->ncols);
3286 new_row = scr->mouse / N_COLS(dconf)((dconf)->scrdata->ncols);
3287 old_cpy_end = scr->cpy_end;
3288 scr->cpy_end = new_row * N_COLS(dconf)((dconf)->scrdata->ncols) + MAXCOL(dconf)(((dconf)->scrdata->ncols) - 1);
3289 if (new_row > old_row)
3290 inverse_region(scr, old_cpy_end + 1, scr->cpy_end);
3291 else if (new_row < old_row)
3292 inverse_region(scr, scr->cpy_end + 1, old_cpy_end);
3293 } else {
3294 /* upper part of the screen */
3295 old_row = scr->cursor / N_COLS(dconf)((dconf)->scrdata->ncols);
3296 new_row = scr->mouse / N_COLS(dconf)((dconf)->scrdata->ncols);
3297 old_cpy_start = scr->cpy_start;
3298 scr->cpy_start = new_row * N_COLS(dconf)((dconf)->scrdata->ncols);
3299 if (new_row < old_row)
3300 inverse_region(scr, scr->cpy_start, old_cpy_start - 1);
3301 else if (new_row > old_row)
3302 inverse_region(scr, old_cpy_start, scr->cpy_start - 1);
3303 }
3304
3305 if (!ISSET(scr->mouse_flags, SEL_EXT_AFTER)((scr->mouse_flags) & (0x08))) {
3306 /* display new cursor */
3307 scr->cursor = scr->mouse;
3308 inverse_char(scr, scr->cursor);
3309 }
3310}
3311
3312/*
3313 * Add an extension to a selected region, word by word
3314 */
3315void
3316mouse_copy_extend_after(struct wsscreen *scr)
3317{
3318 u_int start_dist;
3319 u_int end_dist;
3320
3321 if (ISSET(scr->mouse_flags, SEL_EXISTS)((scr->mouse_flags) & (0x02))) {
3322 SET(scr->mouse_flags, SEL_EXT_AFTER)((scr->mouse_flags) |= (0x08));
3323 mouse_hide(scr); /* hide current cursor */
3324
3325 if (scr->cpy_start > scr->mouse)
3326 start_dist = scr->cpy_start - scr->mouse;
3327 else
3328 start_dist = scr->mouse - scr->cpy_start;
3329 if (scr->mouse > scr->cpy_end)
3330 end_dist = scr->mouse - scr->cpy_end;
3331 else
3332 end_dist = scr->cpy_end - scr->mouse;
3333 if (start_dist < end_dist) {
3334 /* upper part of the screen*/
3335 scr->orig_start = scr->mouse + 1;
3336 /* only used in mouse_copy_extend_line() */
3337 scr->cursor = scr->cpy_start;
3338 } else {
3339 /* lower part of the screen */
3340 scr->orig_start = scr->mouse;
3341 /* only used in mouse_copy_extend_line() */
3342 scr->cursor = scr->cpy_end;
3343 }
3344 if (ISSET(scr->mouse_flags, SEL_BY_CHAR)((scr->mouse_flags) & (0x20)))
3345 mouse_copy_extend_char(scr);
3346 if (ISSET(scr->mouse_flags, SEL_BY_WORD)((scr->mouse_flags) & (0x40)))
3347 mouse_copy_extend_word(scr);
3348 if (ISSET(scr->mouse_flags, SEL_BY_LINE)((scr->mouse_flags) & (0x80)))
3349 mouse_copy_extend_line(scr);
3350 mouse_copy_selection(scr);
3351 }
3352}
3353
3354void
3355mouse_hide(struct wsscreen *scr)
3356{
3357 if (ISSET(scr->mouse_flags, MOUSE_VISIBLE)((scr->mouse_flags) & (0x01))) {
3358 inverse_char(scr, scr->mouse);
3359 CLR(scr->mouse_flags, MOUSE_VISIBLE)((scr->mouse_flags) &= ~(0x01));
3360 }
3361}
3362
3363/*
3364 * Remove a previously selected region
3365 */
3366void
3367remove_selection(struct wsscreen *scr)
3368{
3369 if (ISSET(scr->mouse_flags, SEL_EXT_AFTER)((scr->mouse_flags) & (0x08))) {
3370 /* reset the flag indicating an extension of selection */
3371 CLR(scr->mouse_flags, SEL_EXT_AFTER)((scr->mouse_flags) &= ~(0x08));
3372 }
3373 inverse_region(scr, scr->cpy_start, scr->cpy_end);
3374 CLR(scr->mouse_flags, SEL_IN_PROGRESS | SEL_EXISTS)((scr->mouse_flags) &= ~(0x04 | 0x02));
3375}
3376
3377/*
3378 * Put the current visual selection in the selection buffer
3379 */
3380void
3381mouse_copy_selection(struct wsscreen *scr)
3382{
3383 struct wsscreen_internal *dconf = scr->scr_dconf;
3384 struct wsdisplay_charcell cell;
3385 u_int current = 0;
3386 u_int blank = current;
3387 u_int buf_end = (N_COLS(dconf)((dconf)->scrdata->ncols) + 1) * N_ROWS(dconf)((dconf)->scrdata->nrows);
3388 u_int sel_cur;
3389 u_int sel_end;
3390
3391 sel_cur = scr->cpy_start;
3392 sel_end = scr->cpy_end;
3393
3394 while (sel_cur <= sel_end && current < buf_end - 1) {
3395 if (GETCHAR(scr, sel_cur, &cell)((*(scr)->sc->sc_accessops->getchar) ((scr)->sc->
sc_accesscookie, (sel_cur) / (((scr)->scr_dconf)->scrdata
->ncols), (sel_cur) % (((scr)->scr_dconf)->scrdata->
ncols), &cell))
!= 0)
3396 break;
3397 scr->sc->sc_copybuffer[current] = cell.uc;
3398 if (!IS_SPACE(cell.uc)((cell.uc) == ' '))
3399 blank = current + 1; /* first blank after non-blank */
3400 current++;
3401 if (sel_cur % N_COLS(dconf)((dconf)->scrdata->ncols) == MAXCOL(dconf)(((dconf)->scrdata->ncols) - 1)) {
3402 /*
3403 * If we are on the last column of the screen,
3404 * insert a carriage return.
3405 */
3406 scr->sc->sc_copybuffer[blank] = '\r';
3407 current = ++blank;
3408 }
3409 sel_cur++;
3410 }
3411
3412 scr->sc->sc_copybuffer[current] = '\0';
3413}
3414
3415/*
3416 * Paste the current selection
3417 */
3418void
3419mouse_paste(struct wsscreen *scr)
3420{
3421 char *current = scr->sc->sc_copybuffer;
3422 struct tty *tp;
3423 u_int len;
3424
3425 if (ISSET(scr->sc->sc_flags, SC_PASTE_AVAIL)((scr->sc->sc_flags) & (0x02))) {
3426 if (!WSSCREEN_HAS_TTY(scr)((scr)->scr_tty != ((void *)0)))
3427 return;
3428
3429 tp = scr->scr_tty;
3430 for (len = strlen(scr->sc->sc_copybuffer); len != 0; len--)
3431 (*linesw[tp->t_line].l_rint)(*current++, tp);
3432 }
3433}
3434
3435#ifdef HAVE_SCROLLBACK_SUPPORT
3436/*
3437 * Handle the z axis.
3438 * The z axis (roller or wheel) is mapped by default to scrollback.
3439 */
3440void
3441mouse_zaxis(struct wsscreen *scr, int z)
3442{
3443 if (z < 0)
3444 wsscrollback(scr->sc, WSDISPLAY_SCROLL_BACKWARD0);
3445 else
3446 wsscrollback(scr->sc, WSDISPLAY_SCROLL_FORWARD1);
3447}
3448#endif
3449
3450/*
3451 * Allocate the copy buffer. The size is:
3452 * (cols + 1) * (rows)
3453 * (+1 for '\n' at the end of lines),
3454 * where cols and rows are the maximum of column and rows of all screens.
3455 */
3456void
3457allocate_copybuffer(struct wsdisplay_softc *sc)
3458{
3459 int nscreens = sc->sc_scrdata->nscreens;
3460 int i, s;
3461 const struct wsscreen_descr **screens_list = sc->sc_scrdata->screens;
3462 const struct wsscreen_descr *current;
3463 u_int size = sc->sc_copybuffer_size;
3464
3465 s = spltty()splraise(0x9);
3466 for (i = 0; i < nscreens; i++) {
3467 current = *screens_list;
3468 if ((current->ncols + 1) * current->nrows > size)
3469 size = (current->ncols + 1) * current->nrows;
3470 screens_list++;
3471 }
3472 if (size != sc->sc_copybuffer_size && sc->sc_copybuffer_size != 0) {
3473 bzero(sc->sc_copybuffer, sc->sc_copybuffer_size)__builtin_bzero((sc->sc_copybuffer), (sc->sc_copybuffer_size
))
;
3474 free(sc->sc_copybuffer, M_DEVBUF2, sc->sc_copybuffer_size);
3475 }
3476 if ((sc->sc_copybuffer = (char *)malloc(size, M_DEVBUF2, M_NOWAIT0x0002)) ==
3477 NULL((void *)0)) {
3478 printf("%s: couldn't allocate copy buffer\n",
3479 sc->sc_dv.dv_xname);
3480 size = 0;
3481 }
3482 sc->sc_copybuffer_size = size;
3483 splx(s)spllower(s);
3484}
3485
3486/* Remove selection and cursor on current screen */
3487void
3488mouse_remove(struct wsscreen *scr)
3489{
3490 if (ISSET(scr->mouse_flags, SEL_EXISTS)((scr->mouse_flags) & (0x02)))
3491 remove_selection(scr);
3492
3493 mouse_hide(scr);
3494}
3495
3496#endif /* HAVE_WSMOUSED_SUPPORT */