vt.h revision 257966
11558Srgrimes/*- 21558Srgrimes * Copyright (c) 2009, 2013 The FreeBSD Foundation 31558Srgrimes * All rights reserved. 41558Srgrimes * 51558Srgrimes * This software was developed by Ed Schouten under sponsorship from the 61558Srgrimes * FreeBSD Foundation. 71558Srgrimes * 81558Srgrimes * Portions of this software were developed by Oleksandr Rybalko 91558Srgrimes * under sponsorship from the FreeBSD Foundation. 101558Srgrimes * 111558Srgrimes * Redistribution and use in source and binary forms, with or without 121558Srgrimes * modification, are permitted provided that the following conditions 131558Srgrimes * are met: 141558Srgrimes * 1. Redistributions of source code must retain the above copyright 151558Srgrimes * notice, this list of conditions and the following disclaimer. 161558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 171558Srgrimes * notice, this list of conditions and the following disclaimer in the 181558Srgrimes * documentation and/or other materials provided with the distribution. 191558Srgrimes * 201558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 211558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 241558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301558Srgrimes * SUCH DAMAGE. 311558Srgrimes * 321558Srgrimes * $FreeBSD: user/ed/newcons/sys/dev/vt/vt.h 257966 2013-11-11 11:30:47Z ray $ 331558Srgrimes */ 341558Srgrimes 351558Srgrimes#ifndef _DEV_VT_VT_H_ 3637906Scharnier#define _DEV_VT_VT_H_ 3723685Speter 3837906Scharnier#include <sys/param.h> 391558Srgrimes#include <sys/_lock.h> 401558Srgrimes#include <sys/_mutex.h> 41146754Scharnier#include <sys/callout.h> 42146754Scharnier#include <sys/condvar.h> 43146754Scharnier#include <sys/consio.h> 441558Srgrimes#include <sys/kbio.h> 451558Srgrimes#include <sys/terminal.h> 461558Srgrimes#include <sys/sysctl.h> 471558Srgrimes 4866907Swollman#include "opt_syscons.h" 49167011Smckusick 50167011Smckusick#ifndef VT_MAXWINDOWS 511558Srgrimes#ifdef MAXCONS 52167259Smckusick#define VT_MAXWINDOWS MAXCONS 531558Srgrimes#else 541558Srgrimes#define VT_MAXWINDOWS 12 551558Srgrimes#endif 561558Srgrimes#endif 57103949Smike 5873986Sobrien#define VT_CONSWINDOW 0 591558Srgrimes 60164911Sdwmalone#if defined(SC_TWOBUTTON_MOUSE) || defined(VT_TWOBUTTON_MOUSE) 611558Srgrimes#define VT_MOUSE_PASTEBUTTON MOUSE_BUTTON3DOWN /* right button */ 621558Srgrimes#define VT_MOUSE_EXTENDBUTTON MOUSE_BUTTON2DOWN /* not really used */ 631558Srgrimes#else 6466907Swollman#define VT_MOUSE_PASTEBUTTON MOUSE_BUTTON2DOWN /* middle button */ 65129665Sstefanf#define VT_MOUSE_EXTENDBUTTON MOUSE_BUTTON3DOWN /* right button */ 661558Srgrimes#endif /* defined(SC_TWOBUTTON_MOUSE) || defined(VT_TWOBUTTON_MOUSE) */ 671558Srgrimes 681558Srgrimes#define SC_DRIVER_NAME "vt" 691558Srgrimes#define DPRINTF(_l, ...) if (vt_debug > (_l)) printf( __VA_ARGS__ ) 701558Srgrimes#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 711558Srgrimes 721558Srgrimes#define VT_SYSCTL_INT(_name, _default, _descr) \ 731558Srgrimesstatic int vt_##_name = _default; \ 74128175SgreenSYSCTL_INT(_kern_vt, OID_AUTO, _name, CTLFLAG_RW, &vt_##_name, _default,\ 75128175Sgreen _descr); \ 7621174SguidoTUNABLE_INT("kern.vt." #_name, &vt_##_name); 771558Srgrimes 781558Srgrimesstruct vt_driver; 791558Srgrimes 801558Srgrimesvoid vt_allocate(struct vt_driver *, void *); 81164911Sdwmalonevoid vt_resume(void); 821558Srgrimesvoid vt_suspend(void); 8398542Smckusick 841558Srgrimestypedef unsigned int vt_axis_t; 851558Srgrimes 861558Srgrimes/* 871558Srgrimes * List of locks 8898542Smckusick * (d) locked by vd_lock 891558Srgrimes * (b) locked by vb_lock 901558Srgrimes * (G) locked by Giant 911558Srgrimes * (u) unlocked, locked by higher levels 921558Srgrimes * (c) const until freeing 931558Srgrimes * (?) yet to be determined 941558Srgrimes */ 9598542Smckusick 96144099Simp/* 971558Srgrimes * Per-device datastructure. 981558Srgrimes */ 991558Srgrimes 100167011Smckusickstruct vt_device { 101167011Smckusick struct vt_window *vd_windows[VT_MAXWINDOWS]; /* (c) Windows. */ 10292837Simp struct vt_window *vd_curwindow; /* (d) Current window. */ 10392837Simp struct vt_window *vd_savedwindow;/* (?) Saved for suspend. */ 10492837Simp const struct vt_driver *vd_driver; /* (c) Graphics driver. */ 10592837Simp void *vd_softc; /* (u) Driver data. */ 106167011Smckusick vt_axis_t vd_width; /* (?) Screen width. */ 107167011Smckusick vt_axis_t vd_height; /* (?) Screen height. */ 108167011Smckusick struct mtx vd_lock; /* Per-device lock. */ 109167011Smckusick struct cv vd_winswitch; /* (d) Window switch notify. */ 11092837Simp struct callout vd_timer; /* (d) Display timer. */ 11192837Simp int vd_flags; /* (d) Device flags. */ 11292837Simp#define VDF_TEXTMODE 0x01 /* Do text mode rendering. */ 11392837Simp#define VDF_SPLASH 0x02 /* Splash screen active. */ 11492837Simp#define VDF_ASYNC 0x04 /* vt_timer() running. */ 11592837Simp#define VDF_INVALID 0x08 /* Entire screen should be re-rendered. */ 11692837Simp#define VDF_DEAD 0x10 /* Early probing found nothing. */ 11792837Simp#define VDF_INITIALIZED 0x20 /* vtterm_cnprobe already done. */ 11892837Simp int vd_keyboard; /* (G) Keyboard index. */ 11992837Simp unsigned int vd_unit; /* (c) Device unit. */ 12092837Simp}; 12192837Simp 12292837Simp/* 1231558Srgrimes * Per-window terminal screen buffer. 1241558Srgrimes * 1251558Srgrimes * Because redrawing is performed asynchronously, the buffer keeps track 1261558Srgrimes * of a rectangle that needs to be redrawn (vb_dirtyrect). Because this 1271558Srgrimes * approach seemed to cause suboptimal performance (when the top left 128128175Sgreen * and the bottom right of the screen are modified), it also uses a set 1291558Srgrimes * of bitmasks to keep track of the rows and columns (mod 64) that have 1301558Srgrimes * been modified. 1311558Srgrimes */ 1321558Srgrimes 1331558Srgrimesstruct vt_bufmask { 1341558Srgrimes uint64_t vbm_row, vbm_col; 1351558Srgrimes#define VBM_DIRTY UINT64_MAX 1361558Srgrimes}; 137128175Sgreen 138128175Sgreenstruct vt_buf { 139128175Sgreen struct mtx vb_lock; /* Buffer lock. */ 1401558Srgrimes term_pos_t vb_scr_size; /* (b) Screen dimensions. */ 14123685Speter int vb_flags; /* (b) Flags. */ 1421558Srgrimes#define VBF_CURSOR 0x1 /* Cursor visible. */ 14323685Speter#define VBF_STATIC 0x2 /* Buffer is statically allocated. */ 1441558Srgrimes#define VBF_MTX_INIT 0x4 /* Mutex initialized. */ 1451558Srgrimes#define VBF_SCROLL 0x8 /* scroll locked mode. */ 1461558Srgrimes#define VBF_HISTORY_FULL 0x10 /* All rows filled. */ 1471558Srgrimes int vb_history_size; 1481558Srgrimes#define VBF_DEFAULT_HISTORY_SIZE 500 1491558Srgrimes int vb_roffset; /* (b) History rows offset. */ 1501558Srgrimes int vb_curroffset; /* (b) Saved rows offset. */ 1511558Srgrimes term_pos_t vb_cursor; /* (u) Cursor position. */ 1521558Srgrimes term_rect_t vb_dirtyrect; /* (b) Dirty rectangle. */ 1531558Srgrimes struct vt_bufmask vb_dirtymask; /* (b) Dirty bitmasks. */ 1541558Srgrimes term_char_t *vb_buffer; /* (u) Data buffer. */ 1551558Srgrimes term_char_t **vb_rows; /* (u) Array of rows */ 1561558Srgrimes}; 1571558Srgrimes 1581558Srgrimesvoid vtbuf_copy(struct vt_buf *, const term_rect_t *, const term_pos_t *); 1591558Srgrimesvoid vtbuf_fill_locked(struct vt_buf *, const term_rect_t *, term_char_t); 1601558Srgrimesvoid vtbuf_init_early(struct vt_buf *); 1611558Srgrimesvoid vtbuf_init(struct vt_buf *, const term_pos_t *); 1621558Srgrimesvoid vtbuf_grow(struct vt_buf *, const term_pos_t *, int); 1631558Srgrimesvoid vtbuf_putchar(struct vt_buf *, const term_pos_t *, term_char_t); 1641558Srgrimesvoid vtbuf_cursor_position(struct vt_buf *, const term_pos_t *); 1651558Srgrimesvoid vtbuf_cursor_visibility(struct vt_buf *, int); 1661558Srgrimesvoid vtbuf_undirty(struct vt_buf *, term_rect_t *, struct vt_bufmask *); 1671558Srgrimesvoid vtbuf_sethistory_size(struct vt_buf *, int); 16821174Sguido 16921174Sguido#define VTBUF_SLCK_ENABLE(vb) (vb)->vb_flags |= VBF_SCROLL 17021174Sguido#define VTBUF_SLCK_DISABLE(vb) (vb)->vb_flags &= ~VBF_SCROLL 17121174Sguido 17221174Sguido#define VTBUF_MAX_HEIGHT(vb) \ 1731558Srgrimes ((vb)->vb_history_size) 1741558Srgrimes#define VTBUF_GET_ROW(vb, r) \ 1751558Srgrimes ((vb)->vb_rows[((vb)->vb_roffset + (r)) % VTBUF_MAX_HEIGHT(vb)]) 17692837Simp#define VTBUF_GET_FIELD(vb, r, c) \ 1771558Srgrimes ((vb)->vb_rows[((vb)->vb_roffset + (r)) % VTBUF_MAX_HEIGHT(vb)][(c)]) 17892837Simp#define VTBUF_FIELD(vb, r, c) \ 1791558Srgrimes ((vb)->vb_rows[((vb)->vb_curroffset + (r)) % VTBUF_MAX_HEIGHT(vb)][(c)]) 1801558Srgrimes#define VTBUF_ISCURSOR(vb, r, c) \ 1811558Srgrimes ((vb)->vb_flags & VBF_CURSOR && \ 1821558Srgrimes (vb)->vb_cursor.tp_row == (r) && (vb)->vb_cursor.tp_col == (c)) 1831558Srgrimes#define VTBUF_DIRTYROW(mask, row) \ 184164911Sdwmalone ((mask)->vbm_row & ((uint64_t)1 << ((row) % 64))) 185164911Sdwmalone#define VTBUF_DIRTYCOL(mask, col) \ 1861558Srgrimes ((mask)->vbm_col & ((uint64_t)1 << ((col) % 64))) 1871558Srgrimes#define VTBUF_SPACE_CHAR (' ' | TC_WHITE << 26 | TC_BLACK << 29) 1881558Srgrimes 1891558Srgrimes#define VHS_SET 0 190164911Sdwmalone#define VHS_CUR 1 1911558Srgrimes#define VHS_END 2 1921558Srgrimesint vthistory_seek(struct vt_buf *, int offset, int whence); 1931558Srgrimesvoid vthistory_addlines(struct vt_buf *vb, int offset); 1941558Srgrimesvoid vthistory_getpos(const struct vt_buf *, unsigned int *offset); 1951558Srgrimes 1961558Srgrimes/* 1971558Srgrimes * Per-window datastructure. 1981558Srgrimes */ 19992837Simp 2001558Srgrimesstruct vt_window { 2011558Srgrimes struct vt_device *vw_device; /* (c) Device. */ 2021558Srgrimes struct terminal *vw_terminal; /* (c) Terminal. */ 2031558Srgrimes struct vt_buf vw_buf; /* (u) Screen buffer. */ 2041558Srgrimes struct vt_font *vw_font; /* (d) Graphical font. */ 205128175Sgreen unsigned int vw_number; /* (c) Window number. */ 206128175Sgreen int vw_kbdmode; /* (?) Keyboard mode. */ 207128175Sgreen char *vw_kbdsq; /* Escape sequence queue*/ 208128175Sgreen unsigned int vw_flags; /* (d) Per-window flags. */ 209128175Sgreen#define VWF_BUSY 0x1 /* Busy reconfiguring device. */ 210128175Sgreen#define VWF_OPENED 0x2 /* TTY in use. */ 211128175Sgreen#define VWF_SCROLL 0x4 /* Keys influence scrollback. */ 212128175Sgreen#define VWF_CONSOLE 0x8 /* Kernel message console window. */ 213128175Sgreen#define VWF_VTYLOCK 0x10 /* Prevent window switch. */ 2141558Srgrimes#define VWF_SWWAIT_REL 0x10000 /* Program wait for VT acquire is done. */ 2151558Srgrimes#define VWF_SWWAIT_ACQ 0x20000 /* Program wait for VT release is done. */ 2161558Srgrimes pid_t vw_pid; /* Terminal holding process */ 2171558Srgrimes struct proc *vw_proc; 2181558Srgrimes struct vt_mode vw_smode; /* switch mode */ 2191558Srgrimes struct callout vw_proc_dead_timer; 2201558Srgrimes struct vt_window *vw_switch_to; 2211558Srgrimes}; 2221558Srgrimes 2231558Srgrimes#define VT_AUTO 0 /* switching is automatic */ 2241558Srgrimes#define VT_PROCESS 1 /* switching controlled by prog */ 2251558Srgrimes#define VT_KERNEL 255 /* switching controlled in kernel */ 2261558Srgrimes 2271558Srgrimes#define IS_VT_PROC_MODE(vw) ((vw)->vw_smode.mode == VT_PROCESS) 2281558Srgrimes 2291558Srgrimes/* 2301558Srgrimes * Per-device driver routines. 2311558Srgrimes * 2321558Srgrimes * vd_bitbltchr is used when the driver operates in graphics mode, while 23398542Smckusick * vd_putchar is used when the driver operates in text mode 23498542Smckusick * (VDF_TEXTMODE). 2351558Srgrimes */ 2361558Srgrimes 23798542Smckusicktypedef int vd_init_t(struct vt_device *vd); 2381558Srgrimestypedef void vd_postswitch_t(struct vt_device *vd); 2391558Srgrimestypedef void vd_blank_t(struct vt_device *vd, term_color_t color); 2401558Srgrimestypedef void vd_bitbltchr_t(struct vt_device *vd, const uint8_t *src, 2411558Srgrimes vt_axis_t top, vt_axis_t left, unsigned int width, unsigned int height, 2421558Srgrimes term_color_t fg, term_color_t bg); 2431558Srgrimestypedef void vd_putchar_t(struct vt_device *vd, term_char_t, 2441558Srgrimes vt_axis_t top, vt_axis_t left, term_color_t fg, term_color_t bg); 2451558Srgrimes 2461558Srgrimesstruct vt_driver { 2471558Srgrimes /* Console attachment. */ 2481558Srgrimes vd_init_t *vd_init; 24998542Smckusick 25098542Smckusick /* Drawing. */ 2511558Srgrimes vd_blank_t *vd_blank; 2521558Srgrimes vd_bitbltchr_t *vd_bitbltchr; 2531558Srgrimes 2541558Srgrimes /* Text mode operation. */ 25534851Sjkh vd_putchar_t *vd_putchar; 25634851Sjkh 25734851Sjkh /* Update display setting on vt switch. */ 2581558Srgrimes vd_postswitch_t *vd_postswitch; 2591558Srgrimes 26037240Sbde /* Priority to know which one can override */ 2611558Srgrimes int vd_priority; 2621558Srgrimes#define VD_PRIORITY_DUMB 10 2631558Srgrimes#define VD_PRIORITY_GENERIC 100 2641558Srgrimes#define VD_PRIORITY_SPECIFIC 1000 2651558Srgrimes}; 2661558Srgrimes 2671558Srgrimes/* 26837240Sbde * Console device madness. 2691558Srgrimes * 2701558Srgrimes * Utility macro to make early vt(4) instances work. 2711558Srgrimes */ 2721558Srgrimes 2731558Srgrimesextern const struct terminal_class vt_termclass; 2741558Srgrimesvoid vt_upgrade(struct vt_device *vd); 2751558Srgrimes 2761558Srgrimes#define PIXEL_WIDTH(w) ((w) / 8) 2771558Srgrimes#define PIXEL_HEIGHT(h) ((h) / 16) 2781558Srgrimes 2791558Srgrimes#ifndef VT_FB_DEFAULT_WIDTH 28023685Speter#define VT_FB_DEFAULT_WIDTH 640 28123685Speter#endif 2821558Srgrimes#ifndef VT_FB_DEFAULT_HEIGHT 283167011Smckusick#define VT_FB_DEFAULT_HEIGHT 480 2841558Srgrimes#endif 2851558Srgrimes 2861558Srgrimes#define VT_CONSDEV_DECLARE(driver, width, height, softc) \ 2871558Srgrimesstatic struct terminal driver ## _consterm; \ 2881558Srgrimesstatic struct vt_window driver ## _conswindow; \ 2891558Srgrimesstatic struct vt_device driver ## _consdev = { \ 2901558Srgrimes .vd_driver = &driver, \ 2911558Srgrimes .vd_softc = (softc), \ 2921558Srgrimes .vd_flags = VDF_INVALID, \ 293167011Smckusick .vd_windows = { [VT_CONSWINDOW] = &driver ## _conswindow, }, \ 29423685Speter .vd_curwindow = &driver ## _conswindow, \ 29523685Speter}; \ 29623685Speterstatic term_char_t driver ## _constextbuf[(width) * \ 29723685Speter (VBF_DEFAULT_HISTORY_SIZE)]; \ 29823685Speterstatic term_char_t *driver ## _constextbufrows[ \ 29998542Smckusick VBF_DEFAULT_HISTORY_SIZE]; \ 30090820Siedowsestatic struct vt_window driver ## _conswindow = { \ 30190820Siedowse .vw_number = VT_CONSWINDOW, \ 30290820Siedowse .vw_flags = VWF_CONSOLE, \ 3031558Srgrimes .vw_buf = { \ 3041558Srgrimes .vb_buffer = driver ## _constextbuf, \ 3051558Srgrimes .vb_rows = driver ## _constextbufrows, \ 3061558Srgrimes .vb_history_size = VBF_DEFAULT_HISTORY_SIZE, \ 3071558Srgrimes .vb_curroffset = 0, \ 3081558Srgrimes .vb_roffset = 0, \ 30937906Scharnier .vb_flags = VBF_STATIC, \ 3101558Srgrimes .vb_scr_size = { \ 3111558Srgrimes .tp_row = height, \ 3121558Srgrimes .tp_col = width, \ 31392837Simp }, \ 3141558Srgrimes }, \ 31598542Smckusick .vw_device = &driver ## _consdev, \ 31698542Smckusick .vw_terminal = &driver ## _consterm, \ 3171558Srgrimes .vw_kbdmode = K_XLATE, \ 3181558Srgrimes}; \ 3191558SrgrimesTERMINAL_DECLARE_EARLY(driver ## _consterm, vt_termclass, \ 3201558Srgrimes &driver ## _conswindow); \ 3211558SrgrimesSYSINIT(vt_early_cons, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_ANY, \ 3221558Srgrimes vt_upgrade, &driver ## _consdev) 3231558Srgrimes 3241558Srgrimes/* 32590827Siedowse * Fonts. 32690827Siedowse * 3271558Srgrimes * Remapping tables are used to map Unicode points to glyphs. They need 32869906Siedowse * to be sorted, because vtfont_lookup() performs a binary search. Each 3291558Srgrimes * font has two remapping tables, for normal and bold. When a character 33069906Siedowse * is not present in bold, it uses a normal glyph. When no glyph is 33169906Siedowse * available, it uses glyph 0, which is normally equal to U+FFFD. 33269906Siedowse */ 33369906Siedowse 3341558Srgrimesstruct vt_font_map { 3351558Srgrimes uint32_t vfm_src; 336128175Sgreen uint16_t vfm_dst; 337128175Sgreen uint16_t vfm_len; 338128175Sgreen}; 339128175Sgreen 3401558Srgrimesstruct vt_font { 3411558Srgrimes struct vt_font_map *vf_bold; 3421558Srgrimes struct vt_font_map *vf_normal; 3431558Srgrimes uint8_t *vf_bytes; 3441558Srgrimes unsigned int vf_height, vf_width, 34590608Siedowse vf_normal_length, vf_bold_length; 3461558Srgrimes unsigned int vf_refcount; 34790608Siedowse}; 3481558Srgrimes 3491558Srgrimesconst uint8_t *vtfont_lookup(const struct vt_font *vf, term_char_t c); 3501558Srgrimesstruct vt_font *vtfont_ref(struct vt_font *vf); 35190820Siedowsevoid vtfont_unref(struct vt_font *vf); 3521558Srgrimesint vtfont_load(vfnt_t *f, struct vt_font **ret); 35390820Siedowse 35490820Siedowse/* Sysmouse. */ 35590820Siedowsevoid sysmouse_process_event(mouse_info_t *mi); 35690820Siedowse 35790820Siedowse#endif /* !_DEV_VT_VT_H_ */ 35890820Siedowse