Bug Summary

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