Wed Jan 27 22:42:53 2021 UTC ()
add optional glyph cache for genfb
enable with options GENFB_GLYPHCACHE=n
with n being the desired size of the cache in MB. Should be enough to cache
at least 900 glyphs in whatever video mode used in order to be effective
in 32bit per pixel that's about 1MB


(macallan)
diff -r1.11 -r1.12 src/sys/dev/wsfb/files.wsfb
diff -r1.80 -r1.81 src/sys/dev/wsfb/genfb.c
diff -r1.25 -r1.26 src/sys/dev/wsfb/genfbvar.h

cvs diff -r1.11 -r1.12 src/sys/dev/wsfb/files.wsfb (switch to unified diff)

--- src/sys/dev/wsfb/files.wsfb 2019/07/26 10:48:45 1.11
+++ src/sys/dev/wsfb/files.wsfb 2021/01/27 22:42:53 1.12
@@ -1,15 +1,16 @@ @@ -1,15 +1,16 @@
1# $NetBSD: files.wsfb,v 1.11 2019/07/26 10:48:45 rin Exp $ 1# $NetBSD: files.wsfb,v 1.12 2021/01/27 22:42:53 macallan Exp $
2 2
3# 3#
4# wsdisplay framebuffer drivers 4# wsdisplay framebuffer drivers
5# 5#
6 6
7# some generic flags that drivers may or may not honour 7# some generic flags that drivers may or may not honour
8defflag opt_wsfb.h WSFB_FAKE_VGA_FB # allow mmap(0xa0000) 8defflag opt_wsfb.h WSFB_FAKE_VGA_FB # allow mmap(0xa0000)
9defflag opt_wsfb.h WSFB_ALLOW_OTHERS # allow to mmap() foreign ranges 9defflag opt_wsfb.h WSFB_ALLOW_OTHERS # allow to mmap() foreign ranges
10 10
11# a generic framebuffer console 11# a generic framebuffer console
12define genfb: rasops1, rasops2, rasops4, rasops8, rasops15, rasops16, rasops24, rasops32, vcons, edid 12define genfb: rasops1, rasops2, rasops4, rasops8, rasops15, rasops16, rasops24, rasops32, vcons, edid
13device genfb: genfb, wsemuldisplaydev, drm, splash 13device genfb: genfb, wsemuldisplaydev, drm, splash
14file dev/wsfb/genfb.c genfb needs-flag 14file dev/wsfb/genfb.c genfb needs-flag
15defflag opt_genfb.h GENFB_DEBUG GENFB_SHADOWFB 15defflag opt_genfb.h GENFB_DEBUG GENFB_SHADOWFB
 16defparam opt_genfb.h GENFB_GLYPHCACHE=0 # glyphcache size in MB

cvs diff -r1.80 -r1.81 src/sys/dev/wsfb/genfb.c (switch to unified diff)

--- src/sys/dev/wsfb/genfb.c 2021/01/26 18:08:33 1.80
+++ src/sys/dev/wsfb/genfb.c 2021/01/27 22:42:53 1.81
@@ -1,892 +1,1072 @@ @@ -1,892 +1,1072 @@
1/* $NetBSD: genfb.c,v 1.80 2021/01/26 18:08:33 macallan Exp $ */ 1/* $NetBSD: genfb.c,v 1.81 2021/01/27 22:42:53 macallan Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2007 Michael Lorenz 4 * Copyright (c) 2007 Michael Lorenz
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: genfb.c,v 1.80 2021/01/26 18:08:33 macallan Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: genfb.c,v 1.81 2021/01/27 22:42:53 macallan Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/systm.h> 33#include <sys/systm.h>
34#include <sys/kernel.h> 34#include <sys/kernel.h>
35#include <sys/device.h> 35#include <sys/device.h>
36#include <sys/proc.h> 36#include <sys/proc.h>
37#include <sys/mutex.h> 37#include <sys/mutex.h>
38#include <sys/ioctl.h> 38#include <sys/ioctl.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40#include <sys/systm.h> 40#include <sys/systm.h>
41#include <sys/kmem.h> 41#include <sys/kmem.h>
42#include <sys/reboot.h> 42#include <sys/reboot.h>
43 43
44#include <uvm/uvm_extern.h> 44#include <uvm/uvm_extern.h>
45 45
46#include <dev/wscons/wsconsio.h> 46#include <dev/wscons/wsconsio.h>
47#include <dev/wscons/wsdisplayvar.h> 47#include <dev/wscons/wsdisplayvar.h>
48#include <dev/rasops/rasops.h> 48#include <dev/rasops/rasops.h>
49#include <dev/wsfont/wsfont.h> 49#include <dev/wsfont/wsfont.h>
50 50
51#include <dev/wscons/wsdisplay_vconsvar.h> 51#include <dev/wscons/wsdisplay_vconsvar.h>
52 52
53#include <dev/wsfb/genfbvar.h> 53#include <dev/wsfb/genfbvar.h>
54 54
55#include <dev/videomode/videomode.h> 55#include <dev/videomode/videomode.h>
56#include <dev/videomode/edidvar.h> 56#include <dev/videomode/edidvar.h>
57 57
58#ifdef GENFB_DISABLE_TEXT 58#ifdef GENFB_DISABLE_TEXT
59#define DISABLESPLASH (boothowto & (RB_SINGLE | RB_USERCONF | RB_ASKNAME | \ 59#define DISABLESPLASH (boothowto & (RB_SINGLE | RB_USERCONF | RB_ASKNAME | \
60 AB_VERBOSE | AB_DEBUG) ) 60 AB_VERBOSE | AB_DEBUG) )
61#endif 61#endif
62 62
63#ifdef _KERNEL_OPT 63#ifdef _KERNEL_OPT
64#include "opt_genfb.h" 64#include "opt_genfb.h"
65#include "opt_wsfb.h" 65#include "opt_wsfb.h"
66#include "opt_rasops.h" 66#include "opt_rasops.h"
67#endif 67#endif
68 68
69#ifdef GENFB_DEBUG 69#ifdef GENFB_DEBUG
70#define GPRINTF panic 70#define GPRINTF panic
71#else 71#else
72#define GPRINTF aprint_debug 72#define GPRINTF aprint_debug
73#endif 73#endif
74 74
75#define GENFB_BRIGHTNESS_STEP 15 75#define GENFB_BRIGHTNESS_STEP 15
76#define GENFB_CHAR_WIDTH_MM 3 76#define GENFB_CHAR_WIDTH_MM 3
77 77
78static int genfb_ioctl(void *, void *, u_long, void *, int, struct lwp *); 78static int genfb_ioctl(void *, void *, u_long, void *, int, struct lwp *);
79static paddr_t genfb_mmap(void *, void *, off_t, int); 79static paddr_t genfb_mmap(void *, void *, off_t, int);
80static void genfb_pollc(void *, int); 80static void genfb_pollc(void *, int);
81 81
82static void genfb_init_screen(void *, struct vcons_screen *, int, long *); 82static void genfb_init_screen(void *, struct vcons_screen *, int, long *);
83static int genfb_calc_hsize(struct genfb_softc *); 83static int genfb_calc_hsize(struct genfb_softc *);
84static int genfb_calc_cols(struct genfb_softc *); 84static int genfb_calc_cols(struct genfb_softc *);
85 85
86static int genfb_putcmap(struct genfb_softc *, struct wsdisplay_cmap *); 86static int genfb_putcmap(struct genfb_softc *, struct wsdisplay_cmap *);
87static int genfb_getcmap(struct genfb_softc *, struct wsdisplay_cmap *); 87static int genfb_getcmap(struct genfb_softc *, struct wsdisplay_cmap *);
88static int genfb_putpalreg(struct genfb_softc *, uint8_t, uint8_t, 88static int genfb_putpalreg(struct genfb_softc *, uint8_t, uint8_t,
89 uint8_t, uint8_t); 89 uint8_t, uint8_t);
90static void genfb_init_palette(struct genfb_softc *); 90static void genfb_init_palette(struct genfb_softc *);
91 91
92static void genfb_brightness_up(device_t); 92static void genfb_brightness_up(device_t);
93static void genfb_brightness_down(device_t); 93static void genfb_brightness_down(device_t);
94 94
 95#if GENFB_GLYPHCACHE > 0
 96static int genfb_setup_glyphcache(struct genfb_softc *, long);
 97static void genfb_putchar(void *, int, int, u_int, long);
 98#endif
 99
95extern const u_char rasops_cmap[768]; 100extern const u_char rasops_cmap[768];
96 101
97static int genfb_cnattach_called = 0; 102static int genfb_cnattach_called = 0;
98static int genfb_enabled = 1; 103static int genfb_enabled = 1;
99 104
100static struct genfb_softc *genfb_softc = NULL; 105static struct genfb_softc *genfb_softc = NULL;
101 106
102void 107void
103genfb_init(struct genfb_softc *sc) 108genfb_init(struct genfb_softc *sc)
104{ 109{
105 prop_dictionary_t dict; 110 prop_dictionary_t dict;
106 uint64_t cmap_cb, pmf_cb, mode_cb, bl_cb, br_cb, fbaddr; 111 uint64_t cmap_cb, pmf_cb, mode_cb, bl_cb, br_cb, fbaddr;
107 uint64_t fboffset; 112 uint64_t fboffset;
108 bool console; 113 bool console;
109 114
110 dict = device_properties(sc->sc_dev); 115 dict = device_properties(sc->sc_dev);
111#ifdef GENFB_DEBUG 116#ifdef GENFB_DEBUG
112 printf("%s", prop_dictionary_externalize(dict)); 117 printf("%s", prop_dictionary_externalize(dict));
113#endif 118#endif
114 prop_dictionary_get_bool(dict, "is_console", &console); 119 prop_dictionary_get_bool(dict, "is_console", &console);
115 120
116 if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) { 121 if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) {
117 GPRINTF("no width property\n"); 122 GPRINTF("no width property\n");
118 return; 123 return;
119 } 124 }
120 if (!prop_dictionary_get_uint32(dict, "height", &sc->sc_height)) { 125 if (!prop_dictionary_get_uint32(dict, "height", &sc->sc_height)) {
121 GPRINTF("no height property\n"); 126 GPRINTF("no height property\n");
122 return; 127 return;
123 } 128 }
124 if (!prop_dictionary_get_uint32(dict, "depth", &sc->sc_depth)) { 129 if (!prop_dictionary_get_uint32(dict, "depth", &sc->sc_depth)) {
125 GPRINTF("no depth property\n"); 130 GPRINTF("no depth property\n");
126 return; 131 return;
127 } 132 }
128 133
129 if (!prop_dictionary_get_uint64(dict, "address", &fboffset)) { 134 if (!prop_dictionary_get_uint64(dict, "address", &fboffset)) {
130 GPRINTF("no address property\n"); 135 GPRINTF("no address property\n");
131 return; 136 return;
132 } 137 }
133 138
134 sc->sc_fboffset = (bus_addr_t)fboffset; 139 sc->sc_fboffset = (bus_addr_t)fboffset;
135 140
136 sc->sc_fbaddr = NULL; 141 sc->sc_fbaddr = NULL;
137 if (prop_dictionary_get_uint64(dict, "virtual_address", &fbaddr)) { 142 if (prop_dictionary_get_uint64(dict, "virtual_address", &fbaddr)) {
138 sc->sc_fbaddr = (void *)(uintptr_t)fbaddr; 143 sc->sc_fbaddr = (void *)(uintptr_t)fbaddr;
139 } 144 }
140 145
141 sc->sc_shadowfb = NULL; 146 sc->sc_shadowfb = NULL;
142 if (!prop_dictionary_get_bool(dict, "enable_shadowfb", 147 if (!prop_dictionary_get_bool(dict, "enable_shadowfb",
143 &sc->sc_enable_shadowfb)) 148 &sc->sc_enable_shadowfb))
144#ifdef GENFB_SHADOWFB 149#ifdef GENFB_SHADOWFB
145 sc->sc_enable_shadowfb = true; 150 sc->sc_enable_shadowfb = true;
146#else 151#else
147 sc->sc_enable_shadowfb = false; 152 sc->sc_enable_shadowfb = false;
148#endif 153#endif
149 154
150 if (!prop_dictionary_get_uint32(dict, "linebytes", &sc->sc_stride)) 155 if (!prop_dictionary_get_uint32(dict, "linebytes", &sc->sc_stride))
151 sc->sc_stride = (sc->sc_width * sc->sc_depth) >> 3; 156 sc->sc_stride = (sc->sc_width * sc->sc_depth) >> 3;
152 157
153 /* 158 /*
154 * deal with a bug in the Raptor firmware which always sets 159 * deal with a bug in the Raptor firmware which always sets
155 * stride = width even when depth != 8 160 * stride = width even when depth != 8
156 */ 161 */
157 if (sc->sc_stride < sc->sc_width * (sc->sc_depth >> 3)) 162 if (sc->sc_stride < sc->sc_width * (sc->sc_depth >> 3))
158 sc->sc_stride = sc->sc_width * (sc->sc_depth >> 3); 163 sc->sc_stride = sc->sc_width * (sc->sc_depth >> 3);
159 164
160 sc->sc_fbsize = sc->sc_height * sc->sc_stride; 165 sc->sc_fbsize = sc->sc_height * sc->sc_stride;
161 166
162 /* optional colour map callback */ 167 /* optional colour map callback */
163 sc->sc_cmcb = NULL; 168 sc->sc_cmcb = NULL;
164 if (prop_dictionary_get_uint64(dict, "cmap_callback", &cmap_cb)) { 169 if (prop_dictionary_get_uint64(dict, "cmap_callback", &cmap_cb)) {
165 if (cmap_cb != 0) 170 if (cmap_cb != 0)
166 sc->sc_cmcb = (void *)(vaddr_t)cmap_cb; 171 sc->sc_cmcb = (void *)(vaddr_t)cmap_cb;
167 } 172 }
168 173
169 /* optional pmf callback */ 174 /* optional pmf callback */
170 sc->sc_pmfcb = NULL; 175 sc->sc_pmfcb = NULL;
171 if (prop_dictionary_get_uint64(dict, "pmf_callback", &pmf_cb)) { 176 if (prop_dictionary_get_uint64(dict, "pmf_callback", &pmf_cb)) {
172 if (pmf_cb != 0) 177 if (pmf_cb != 0)
173 sc->sc_pmfcb = (void *)(vaddr_t)pmf_cb; 178 sc->sc_pmfcb = (void *)(vaddr_t)pmf_cb;
174 } 179 }
175 180
176 /* optional mode callback */ 181 /* optional mode callback */
177 sc->sc_modecb = NULL; 182 sc->sc_modecb = NULL;
178 if (prop_dictionary_get_uint64(dict, "mode_callback", &mode_cb)) { 183 if (prop_dictionary_get_uint64(dict, "mode_callback", &mode_cb)) {
179 if (mode_cb != 0) 184 if (mode_cb != 0)
180 sc->sc_modecb = (void *)(vaddr_t)mode_cb; 185 sc->sc_modecb = (void *)(vaddr_t)mode_cb;
181 } 186 }
182 187
183 /* optional backlight control callback */ 188 /* optional backlight control callback */
184 sc->sc_backlight = NULL; 189 sc->sc_backlight = NULL;
185 if (prop_dictionary_get_uint64(dict, "backlight_callback", &bl_cb)) { 190 if (prop_dictionary_get_uint64(dict, "backlight_callback", &bl_cb)) {
186 if (bl_cb != 0) { 191 if (bl_cb != 0) {
187 sc->sc_backlight = (void *)(vaddr_t)bl_cb; 192 sc->sc_backlight = (void *)(vaddr_t)bl_cb;
188 aprint_naive_dev(sc->sc_dev, 193 aprint_naive_dev(sc->sc_dev,
189 "enabling backlight control\n"); 194 "enabling backlight control\n");
190 } 195 }
191 } 196 }
192 197
193 /* optional brightness control callback */ 198 /* optional brightness control callback */
194 sc->sc_brightness = NULL; 199 sc->sc_brightness = NULL;
195 if (prop_dictionary_get_uint64(dict, "brightness_callback", &br_cb)) { 200 if (prop_dictionary_get_uint64(dict, "brightness_callback", &br_cb)) {
196 if (br_cb != 0) { 201 if (br_cb != 0) {
197 sc->sc_brightness = (void *)(vaddr_t)br_cb; 202 sc->sc_brightness = (void *)(vaddr_t)br_cb;
198 aprint_naive_dev(sc->sc_dev, 203 aprint_naive_dev(sc->sc_dev,
199 "enabling brightness control\n"); 204 "enabling brightness control\n");
200 if (console && 205 if (console &&
201 sc->sc_brightness->gpc_upd_parameter != NULL) { 206 sc->sc_brightness->gpc_upd_parameter != NULL) {
202 pmf_event_register(sc->sc_dev, 207 pmf_event_register(sc->sc_dev,
203 PMFE_DISPLAY_BRIGHTNESS_UP, 208 PMFE_DISPLAY_BRIGHTNESS_UP,
204 genfb_brightness_up, TRUE); 209 genfb_brightness_up, TRUE);
205 pmf_event_register(sc->sc_dev, 210 pmf_event_register(sc->sc_dev,
206 PMFE_DISPLAY_BRIGHTNESS_DOWN, 211 PMFE_DISPLAY_BRIGHTNESS_DOWN,
207 genfb_brightness_down, TRUE); 212 genfb_brightness_down, TRUE);
208 } 213 }
209 } 214 }
210 } 215 }
211} 216}
212 217
213int 218int
214genfb_attach(struct genfb_softc *sc, struct genfb_ops *ops) 219genfb_attach(struct genfb_softc *sc, struct genfb_ops *ops)
215{ 220{
216 struct wsemuldisplaydev_attach_args aa; 221 struct wsemuldisplaydev_attach_args aa;
217 prop_dictionary_t dict; 222 prop_dictionary_t dict;
218 struct rasops_info *ri; 223 struct rasops_info *ri;
219 paddr_t fb_phys; 224 paddr_t fb_phys;
220 uint16_t crow; 225 uint16_t crow;
221 long defattr; 226 long defattr;
222 bool console; 227 bool console;
223#ifdef SPLASHSCREEN 228#ifdef SPLASHSCREEN
224 int i, j; 229 int i, j;
225 int error = ENXIO; 230 int error = ENXIO;
226#endif 231#endif
227 232
228 dict = device_properties(sc->sc_dev); 233 dict = device_properties(sc->sc_dev);
229 prop_dictionary_get_bool(dict, "is_console", &console); 234 prop_dictionary_get_bool(dict, "is_console", &console);
230 235
231 if (prop_dictionary_get_uint16(dict, "cursor-row", &crow) == false) 236 if (prop_dictionary_get_uint16(dict, "cursor-row", &crow) == false)
232 crow = 0; 237 crow = 0;
233 if (prop_dictionary_get_bool(dict, "clear-screen", &sc->sc_want_clear) 238 if (prop_dictionary_get_bool(dict, "clear-screen", &sc->sc_want_clear)
234 == false) 239 == false)
235 sc->sc_want_clear = true; 240 sc->sc_want_clear = true;
236 241
237 fb_phys = (paddr_t)sc->sc_fboffset; 242 fb_phys = (paddr_t)sc->sc_fboffset;
238 if (fb_phys == 0) { 243 if (fb_phys == 0) {
239 KASSERT(sc->sc_fbaddr != NULL); 244 KASSERT(sc->sc_fbaddr != NULL);
240 (void)pmap_extract(pmap_kernel(), (vaddr_t)sc->sc_fbaddr, 245 (void)pmap_extract(pmap_kernel(), (vaddr_t)sc->sc_fbaddr,
241 &fb_phys); 246 &fb_phys);
242 } 247 }
243 248
244 aprint_verbose_dev(sc->sc_dev, "framebuffer at %p, size %dx%d, depth %d, " 249 aprint_verbose_dev(sc->sc_dev, "framebuffer at %p, size %dx%d, depth %d, "
245 "stride %d\n", 250 "stride %d\n",
246 fb_phys ? (void *)(intptr_t)fb_phys : sc->sc_fbaddr, 251 fb_phys ? (void *)(intptr_t)fb_phys : sc->sc_fbaddr,
247 sc->sc_width, sc->sc_height, sc->sc_depth, sc->sc_stride); 252 sc->sc_width, sc->sc_height, sc->sc_depth, sc->sc_stride);
248 253
249 sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 254 sc->sc_defaultscreen_descr = (struct wsscreen_descr){
250 "default", 255 "default",
251 0, 0, 256 0, 0,
252 NULL, 257 NULL,
253 8, 16, 258 8, 16,
254 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 259 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
255 WSSCREEN_RESIZE, 260 WSSCREEN_RESIZE,
256 NULL 261 NULL
257 }; 262 };
258 sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 263 sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
259 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 264 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
260 memcpy(&sc->sc_ops, ops, sizeof(struct genfb_ops)); 265 memcpy(&sc->sc_ops, ops, sizeof(struct genfb_ops));
261 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 266 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
262 if (sc->sc_modecb != NULL) 267 if (sc->sc_modecb != NULL)
263 sc->sc_modecb->gmc_setmode(sc, sc->sc_mode); 268 sc->sc_modecb->gmc_setmode(sc, sc->sc_mode);
264 269
265 sc->sc_accessops.ioctl = genfb_ioctl; 270 sc->sc_accessops.ioctl = genfb_ioctl;
266 sc->sc_accessops.mmap = genfb_mmap; 271 sc->sc_accessops.mmap = genfb_mmap;
267 sc->sc_accessops.pollc = genfb_pollc; 272 sc->sc_accessops.pollc = genfb_pollc;
268 273
269 if (sc->sc_enable_shadowfb) { 274 if (sc->sc_enable_shadowfb) {
270 sc->sc_shadowfb = kmem_alloc(sc->sc_fbsize, KM_SLEEP); 275 sc->sc_shadowfb = kmem_alloc(sc->sc_fbsize, KM_SLEEP);
271 if (sc->sc_want_clear == false) 276 if (sc->sc_want_clear == false)
272 memcpy(sc->sc_shadowfb, sc->sc_fbaddr, sc->sc_fbsize); 277 memcpy(sc->sc_shadowfb, sc->sc_fbaddr, sc->sc_fbsize);
273 aprint_verbose_dev(sc->sc_dev, 278 aprint_verbose_dev(sc->sc_dev,
274 "shadow framebuffer enabled, size %zu KB\n", 279 "shadow framebuffer enabled, size %zu KB\n",
275 sc->sc_fbsize >> 10); 280 sc->sc_fbsize >> 10);
276 } 281 }
277 282
278 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, 283 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
279 &sc->sc_accessops); 284 &sc->sc_accessops);
280 sc->vd.init_screen = genfb_init_screen; 285 sc->vd.init_screen = genfb_init_screen;
281 286
282 /* Do not print anything between this point and the screen 287 /* Do not print anything between this point and the screen
283 * clear operation below. Otherwise it will be lost. */ 288 * clear operation below. Otherwise it will be lost. */
284 289
285 ri = &sc->sc_console_screen.scr_ri; 290 ri = &sc->sc_console_screen.scr_ri;
286 291
287 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, 292 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
288 &defattr); 293 &defattr);
289 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 294 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
290 295
 296#if GENFB_GLYPHCACHE > 0
 297 genfb_setup_glyphcache(sc, defattr);
 298#endif
 299
291#ifdef SPLASHSCREEN 300#ifdef SPLASHSCREEN
292/* 301/*
293 * If system isn't going to go multiuser, or user has requested to see 302 * If system isn't going to go multiuser, or user has requested to see
294 * boot text, don't render splash screen immediately 303 * boot text, don't render splash screen immediately
295 */ 304 */
296 if (DISABLESPLASH) 305 if (DISABLESPLASH)
297#endif 306#endif
298 vcons_redraw_screen(&sc->sc_console_screen); 307 vcons_redraw_screen(&sc->sc_console_screen);
299 308
300 sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 309 sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
301 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 310 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
302 sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 311 sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
303 sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 312 sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
304 313
305 if (crow >= ri->ri_rows) { 314 if (crow >= ri->ri_rows) {
306 crow = 0; 315 crow = 0;
307 sc->sc_want_clear = 1; 316 sc->sc_want_clear = 1;
308 } 317 }
309 318
310 if (console) 319 if (console)
311 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, crow, 320 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, crow,
312 defattr); 321 defattr);
313 322
314 /* Clear the whole screen to bring it to a known state. */ 323 /* Clear the whole screen to bring it to a known state. */
315 if (sc->sc_want_clear) 324 if (sc->sc_want_clear)
316 (*ri->ri_ops.eraserows)(ri, 0, ri->ri_rows, defattr); 325 (*ri->ri_ops.eraserows)(ri, 0, ri->ri_rows, defattr);
317 326
318#ifdef SPLASHSCREEN 327#ifdef SPLASHSCREEN
319 j = 0; 328 j = 0;
320 for (i = 0; i < uimin(1 << sc->sc_depth, 256); i++) { 329 for (i = 0; i < uimin(1 << sc->sc_depth, 256); i++) {
321 if (i >= SPLASH_CMAP_OFFSET && 330 if (i >= SPLASH_CMAP_OFFSET &&
322 i < SPLASH_CMAP_OFFSET + SPLASH_CMAP_SIZE) { 331 i < SPLASH_CMAP_OFFSET + SPLASH_CMAP_SIZE) {
323 splash_get_cmap(i, 332 splash_get_cmap(i,
324 &sc->sc_cmap_red[i], 333 &sc->sc_cmap_red[i],
325 &sc->sc_cmap_green[i], 334 &sc->sc_cmap_green[i],
326 &sc->sc_cmap_blue[i]); 335 &sc->sc_cmap_blue[i]);
327 } else { 336 } else {
328 sc->sc_cmap_red[i] = rasops_cmap[j]; 337 sc->sc_cmap_red[i] = rasops_cmap[j];
329 sc->sc_cmap_green[i] = rasops_cmap[j + 1]; 338 sc->sc_cmap_green[i] = rasops_cmap[j + 1];
330 sc->sc_cmap_blue[i] = rasops_cmap[j + 2]; 339 sc->sc_cmap_blue[i] = rasops_cmap[j + 2];
331 } 340 }
332 j += 3; 341 j += 3;
333 } 342 }
334 genfb_restore_palette(sc); 343 genfb_restore_palette(sc);
335 344
336 sc->sc_splash.si_depth = sc->sc_depth; 345 sc->sc_splash.si_depth = sc->sc_depth;
337 sc->sc_splash.si_bits = sc->sc_console_screen.scr_ri.ri_origbits; 346 sc->sc_splash.si_bits = sc->sc_console_screen.scr_ri.ri_origbits;
338 sc->sc_splash.si_hwbits = sc->sc_fbaddr; 347 sc->sc_splash.si_hwbits = sc->sc_fbaddr;
339 sc->sc_splash.si_width = sc->sc_width; 348 sc->sc_splash.si_width = sc->sc_width;
340 sc->sc_splash.si_height = sc->sc_height; 349 sc->sc_splash.si_height = sc->sc_height;
341 sc->sc_splash.si_stride = sc->sc_stride; 350 sc->sc_splash.si_stride = sc->sc_stride;
342 sc->sc_splash.si_fillrect = NULL; 351 sc->sc_splash.si_fillrect = NULL;
343 if (!DISABLESPLASH) { 352 if (!DISABLESPLASH) {
344 error = splash_render(&sc->sc_splash, 353 error = splash_render(&sc->sc_splash,
345 SPLASH_F_CENTER|SPLASH_F_FILL); 354 SPLASH_F_CENTER|SPLASH_F_FILL);
346 if (error) { 355 if (error) {
347 SCREEN_ENABLE_DRAWING(&sc->sc_console_screen); 356 SCREEN_ENABLE_DRAWING(&sc->sc_console_screen);
348 genfb_init_palette(sc); 357 genfb_init_palette(sc);
349 vcons_replay_msgbuf(&sc->sc_console_screen); 358 vcons_replay_msgbuf(&sc->sc_console_screen);
350 } 359 }
351 } 360 }
352#else 361#else
353 genfb_init_palette(sc); 362 genfb_init_palette(sc);
354 if (console && (boothowto & (AB_SILENT|AB_QUIET)) == 0) 363 if (console && (boothowto & (AB_SILENT|AB_QUIET)) == 0)
355 vcons_replay_msgbuf(&sc->sc_console_screen); 364 vcons_replay_msgbuf(&sc->sc_console_screen);
356#endif 365#endif
357 366
358 if (genfb_softc == NULL) 367 if (genfb_softc == NULL)
359 genfb_softc = sc; 368 genfb_softc = sc;
360 369
361 aa.console = console; 370 aa.console = console;
362 aa.scrdata = &sc->sc_screenlist; 371 aa.scrdata = &sc->sc_screenlist;
363 aa.accessops = &sc->sc_accessops; 372 aa.accessops = &sc->sc_accessops;
364 aa.accesscookie = &sc->vd; 373 aa.accesscookie = &sc->vd;
365 374
366#ifdef GENFB_DISABLE_TEXT 375#ifdef GENFB_DISABLE_TEXT
367 if (!DISABLESPLASH && error == 0) 376 if (!DISABLESPLASH && error == 0)
368 SCREEN_DISABLE_DRAWING(&sc->sc_console_screen); 377 SCREEN_DISABLE_DRAWING(&sc->sc_console_screen);
369#endif 378#endif
370 379
371 config_found_ia(sc->sc_dev, "wsemuldisplaydev", &aa, 380 config_found_ia(sc->sc_dev, "wsemuldisplaydev", &aa,
372 wsemuldisplaydevprint); 381 wsemuldisplaydevprint);
373 382
374 return 0; 383 return 0;
375} 384}
376 385
377static int 386static int
378genfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 387genfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
379 struct lwp *l) 388 struct lwp *l)
380{ 389{
381 struct vcons_data *vd = v; 390 struct vcons_data *vd = v;
382 struct genfb_softc *sc = vd->cookie; 391 struct genfb_softc *sc = vd->cookie;
383 struct wsdisplay_fbinfo *wdf; 392 struct wsdisplay_fbinfo *wdf;
384 struct vcons_screen *ms = vd->active; 393 struct vcons_screen *ms = vd->active;
385 struct wsdisplay_param *param; 394 struct wsdisplay_param *param;
386 int new_mode, error, val, ret; 395 int new_mode, error, val, ret;
387 396
388 switch (cmd) { 397 switch (cmd) {
389 case WSDISPLAYIO_GINFO: 398 case WSDISPLAYIO_GINFO:
390 if (ms == NULL) 399 if (ms == NULL)
391 return ENODEV; 400 return ENODEV;
392 wdf = (void *)data; 401 wdf = (void *)data;
393 wdf->height = ms->scr_ri.ri_height; 402 wdf->height = ms->scr_ri.ri_height;
394 wdf->width = ms->scr_ri.ri_width; 403 wdf->width = ms->scr_ri.ri_width;
395 wdf->depth = ms->scr_ri.ri_depth; 404 wdf->depth = ms->scr_ri.ri_depth;
396 wdf->cmsize = 256; 405 wdf->cmsize = 256;
397 return 0; 406 return 0;
398 407
399 case WSDISPLAYIO_GETCMAP: 408 case WSDISPLAYIO_GETCMAP:
400 return genfb_getcmap(sc, 409 return genfb_getcmap(sc,
401 (struct wsdisplay_cmap *)data); 410 (struct wsdisplay_cmap *)data);
402 411
403 case WSDISPLAYIO_PUTCMAP: 412 case WSDISPLAYIO_PUTCMAP:
404 return genfb_putcmap(sc, 413 return genfb_putcmap(sc,
405 (struct wsdisplay_cmap *)data); 414 (struct wsdisplay_cmap *)data);
406 415
407 case WSDISPLAYIO_LINEBYTES: 416 case WSDISPLAYIO_LINEBYTES:
408 *(u_int *)data = sc->sc_stride; 417 *(u_int *)data = sc->sc_stride;
409 return 0; 418 return 0;
410 419
411 case WSDISPLAYIO_SMODE: 420 case WSDISPLAYIO_SMODE:
412 new_mode = *(int *)data; 421 new_mode = *(int *)data;
413 422
414 /* notify the bus backend */ 423 /* notify the bus backend */
415 error = 0; 424 error = 0;
416 if (sc->sc_ops.genfb_ioctl) 425 if (sc->sc_ops.genfb_ioctl)
417 error = sc->sc_ops.genfb_ioctl(sc, vs, 426 error = sc->sc_ops.genfb_ioctl(sc, vs,
418 cmd, data, flag, l); 427 cmd, data, flag, l);
419 if (error && error != EPASSTHROUGH) 428 if (error && error != EPASSTHROUGH)
420 return error; 429 return error;
421 430
422 if (new_mode != sc->sc_mode) { 431 if (new_mode != sc->sc_mode) {
423 sc->sc_mode = new_mode; 432 sc->sc_mode = new_mode;
424 if (sc->sc_modecb != NULL) 433 if (sc->sc_modecb != NULL)
425 sc->sc_modecb->gmc_setmode(sc, 434 sc->sc_modecb->gmc_setmode(sc,
426 sc->sc_mode); 435 sc->sc_mode);
427 if (new_mode == WSDISPLAYIO_MODE_EMUL) { 436 if (new_mode == WSDISPLAYIO_MODE_EMUL) {
428 genfb_restore_palette(sc); 437 genfb_restore_palette(sc);
429 vcons_redraw_screen(ms); 438 vcons_redraw_screen(ms);
430 } 439 }
431 } 440 }
432 return 0; 441 return 0;
433  442
434 case WSDISPLAYIO_SSPLASH: 443 case WSDISPLAYIO_SSPLASH:
435#if defined(SPLASHSCREEN) 444#if defined(SPLASHSCREEN)
436 if(*(int *)data == 1) { 445 if(*(int *)data == 1) {
437 SCREEN_DISABLE_DRAWING(&sc->sc_console_screen); 446 SCREEN_DISABLE_DRAWING(&sc->sc_console_screen);
438 splash_render(&sc->sc_splash, 447 splash_render(&sc->sc_splash,
439 SPLASH_F_CENTER|SPLASH_F_FILL); 448 SPLASH_F_CENTER|SPLASH_F_FILL);
440 } else { 449 } else {
441 SCREEN_ENABLE_DRAWING(&sc->sc_console_screen); 450 SCREEN_ENABLE_DRAWING(&sc->sc_console_screen);
442 genfb_init_palette(sc); 451 genfb_init_palette(sc);
443 } 452 }
444 vcons_redraw_screen(ms); 453 vcons_redraw_screen(ms);
445 return 0; 454 return 0;
446#else 455#else
447 return ENODEV; 456 return ENODEV;
448#endif 457#endif
449 case WSDISPLAYIO_GETPARAM: 458 case WSDISPLAYIO_GETPARAM:
450 param = (struct wsdisplay_param *)data; 459 param = (struct wsdisplay_param *)data;
451 switch (param->param) { 460 switch (param->param) {
452 case WSDISPLAYIO_PARAM_BRIGHTNESS: 461 case WSDISPLAYIO_PARAM_BRIGHTNESS:
453 if (sc->sc_brightness == NULL) 462 if (sc->sc_brightness == NULL)
454 return EPASSTHROUGH; 463 return EPASSTHROUGH;
455 param->min = 0; 464 param->min = 0;
456 param->max = 255; 465 param->max = 255;
457 return sc->sc_brightness->gpc_get_parameter( 466 return sc->sc_brightness->gpc_get_parameter(
458 sc->sc_brightness->gpc_cookie, 467 sc->sc_brightness->gpc_cookie,
459 &param->curval); 468 &param->curval);
460 case WSDISPLAYIO_PARAM_BACKLIGHT: 469 case WSDISPLAYIO_PARAM_BACKLIGHT:
461 if (sc->sc_backlight == NULL) 470 if (sc->sc_backlight == NULL)
462 return EPASSTHROUGH; 471 return EPASSTHROUGH;
463 param->min = 0; 472 param->min = 0;
464 param->max = 1; 473 param->max = 1;
465 return sc->sc_backlight->gpc_get_parameter( 474 return sc->sc_backlight->gpc_get_parameter(
466 sc->sc_backlight->gpc_cookie, 475 sc->sc_backlight->gpc_cookie,
467 &param->curval); 476 &param->curval);
468 } 477 }
469 return EPASSTHROUGH; 478 return EPASSTHROUGH;
470 479
471 case WSDISPLAYIO_SETPARAM: 480 case WSDISPLAYIO_SETPARAM:
472 param = (struct wsdisplay_param *)data; 481 param = (struct wsdisplay_param *)data;
473 switch (param->param) { 482 switch (param->param) {
474 case WSDISPLAYIO_PARAM_BRIGHTNESS: 483 case WSDISPLAYIO_PARAM_BRIGHTNESS:
475 if (sc->sc_brightness == NULL) 484 if (sc->sc_brightness == NULL)
476 return EPASSTHROUGH; 485 return EPASSTHROUGH;
477 val = param->curval; 486 val = param->curval;
478 if (val < 0) val = 0; 487 if (val < 0) val = 0;
479 if (val > 255) val = 255; 488 if (val > 255) val = 255;
480 return sc->sc_brightness->gpc_set_parameter( 489 return sc->sc_brightness->gpc_set_parameter(
481 sc->sc_brightness->gpc_cookie, val); 490 sc->sc_brightness->gpc_cookie, val);
482 case WSDISPLAYIO_PARAM_BACKLIGHT: 491 case WSDISPLAYIO_PARAM_BACKLIGHT:
483 if (sc->sc_backlight == NULL) 492 if (sc->sc_backlight == NULL)
484 return EPASSTHROUGH; 493 return EPASSTHROUGH;
485 val = param->curval; 494 val = param->curval;
486 if (val < 0) val = 0; 495 if (val < 0) val = 0;
487 if (val > 1) val = 1; 496 if (val > 1) val = 1;
488 return sc->sc_backlight->gpc_set_parameter( 497 return sc->sc_backlight->gpc_set_parameter(
489 sc->sc_backlight->gpc_cookie, val); 498 sc->sc_backlight->gpc_cookie, val);
490 } 499 }
491 return EPASSTHROUGH;  500 return EPASSTHROUGH;
492 } 501 }
493 ret = EPASSTHROUGH; 502 ret = EPASSTHROUGH;
494 if (sc->sc_ops.genfb_ioctl) 503 if (sc->sc_ops.genfb_ioctl)
495 ret = sc->sc_ops.genfb_ioctl(sc, vs, cmd, data, flag, l); 504 ret = sc->sc_ops.genfb_ioctl(sc, vs, cmd, data, flag, l);
496 if (ret != EPASSTHROUGH) 505 if (ret != EPASSTHROUGH)
497 return ret; 506 return ret;
498 /* 507 /*
499 * XXX 508 * XXX
500 * handle these only if there either is no ioctl() handler or it didn't 509 * handle these only if there either is no ioctl() handler or it didn't
501 * know how to deal with them. This allows bus frontends to override 510 * know how to deal with them. This allows bus frontends to override
502 * them but still provides fallback implementations 511 * them but still provides fallback implementations
503 */ 512 */
504 switch (cmd) { 513 switch (cmd) {
505 case WSDISPLAYIO_GET_EDID: { 514 case WSDISPLAYIO_GET_EDID: {
506 struct wsdisplayio_edid_info *d = data; 515 struct wsdisplayio_edid_info *d = data;
507 return wsdisplayio_get_edid(sc->sc_dev, d); 516 return wsdisplayio_get_edid(sc->sc_dev, d);
508 } 517 }
509  518
510 case WSDISPLAYIO_GET_FBINFO: { 519 case WSDISPLAYIO_GET_FBINFO: {
511 struct wsdisplayio_fbinfo *fbi = data; 520 struct wsdisplayio_fbinfo *fbi = data;
512 return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 521 return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
513 } 522 }
514 } 523 }
515 return EPASSTHROUGH; 524 return EPASSTHROUGH;
516} 525}
517 526
518static paddr_t 527static paddr_t
519genfb_mmap(void *v, void *vs, off_t offset, int prot) 528genfb_mmap(void *v, void *vs, off_t offset, int prot)
520{ 529{
521 struct vcons_data *vd = v; 530 struct vcons_data *vd = v;
522 struct genfb_softc *sc = vd->cookie; 531 struct genfb_softc *sc = vd->cookie;
523 532
524 if (sc->sc_ops.genfb_mmap) 533 if (sc->sc_ops.genfb_mmap)
525 return sc->sc_ops.genfb_mmap(sc, vs, offset, prot); 534 return sc->sc_ops.genfb_mmap(sc, vs, offset, prot);
526 535
527 return -1; 536 return -1;
528} 537}
529 538
530static void 539static void
531genfb_pollc(void *v, int on) 540genfb_pollc(void *v, int on)
532{ 541{
533 struct vcons_data *vd = v; 542 struct vcons_data *vd = v;
534 struct genfb_softc *sc = vd->cookie; 543 struct genfb_softc *sc = vd->cookie;
535 544
536 if (sc == NULL) 545 if (sc == NULL)
537 return; 546 return;
538 547
539 if (on) 548 if (on)
540 genfb_enable_polling(sc->sc_dev); 549 genfb_enable_polling(sc->sc_dev);
541 else 550 else
542 genfb_disable_polling(sc->sc_dev); 551 genfb_disable_polling(sc->sc_dev);
543} 552}
544 553
545static void 554static void
546genfb_init_screen(void *cookie, struct vcons_screen *scr, 555genfb_init_screen(void *cookie, struct vcons_screen *scr,
547 int existing, long *defattr) 556 int existing, long *defattr)
548{ 557{
549 struct genfb_softc *sc = cookie; 558 struct genfb_softc *sc = cookie;
550 struct rasops_info *ri = &scr->scr_ri; 559 struct rasops_info *ri = &scr->scr_ri;
551 int wantcols; 560 int wantcols;
552 bool is_bgr, is_swapped; 561 bool is_bgr, is_swapped;
553 562
554 ri->ri_depth = sc->sc_depth; 563 ri->ri_depth = sc->sc_depth;
555 ri->ri_width = sc->sc_width; 564 ri->ri_width = sc->sc_width;
556 ri->ri_height = sc->sc_height; 565 ri->ri_height = sc->sc_height;
557 ri->ri_stride = sc->sc_stride; 566 ri->ri_stride = sc->sc_stride;
558 ri->ri_flg = RI_CENTER; 567 ri->ri_flg = RI_CENTER;
559 if (sc->sc_want_clear) 568 if (sc->sc_want_clear)
560 ri->ri_flg |= RI_FULLCLEAR; 569 ri->ri_flg |= RI_FULLCLEAR;
561 570
562 scr->scr_flags |= VCONS_LOADFONT; 571 scr->scr_flags |= VCONS_LOADFONT;
563 572
564 if (sc->sc_shadowfb != NULL) { 573 if (sc->sc_shadowfb != NULL) {
565 ri->ri_hwbits = (char *)sc->sc_fbaddr; 574 ri->ri_hwbits = (char *)sc->sc_fbaddr;
566 ri->ri_bits = (char *)sc->sc_shadowfb; 575 ri->ri_bits = (char *)sc->sc_shadowfb;
567 } else { 576 } else {
568 ri->ri_bits = (char *)sc->sc_fbaddr; 577 ri->ri_bits = (char *)sc->sc_fbaddr;
569 scr->scr_flags |= VCONS_DONT_READ; 578 scr->scr_flags |= VCONS_DONT_READ;
570 } 579 }
571 580
572 if (existing && sc->sc_want_clear) 581 if (existing && sc->sc_want_clear)
573 ri->ri_flg |= RI_CLEAR; 582 ri->ri_flg |= RI_CLEAR;
574 583
575 switch (ri->ri_depth) { 584 switch (ri->ri_depth) {
576 case 32: 585 case 32:
577 case 24: 586 case 24:
578 ri->ri_rnum = ri->ri_gnum = ri->ri_bnum = 8; 587 ri->ri_rnum = ri->ri_gnum = ri->ri_bnum = 8;
579 ri->ri_flg |= RI_ENABLE_ALPHA; 588 ri->ri_flg |= RI_ENABLE_ALPHA;
580 589
581 is_bgr = false; 590 is_bgr = false;
582 prop_dictionary_get_bool(device_properties(sc->sc_dev), 591 prop_dictionary_get_bool(device_properties(sc->sc_dev),
583 "is_bgr", &is_bgr); 592 "is_bgr", &is_bgr);
584 593
585 is_swapped = false; 594 is_swapped = false;
586 prop_dictionary_get_bool(device_properties(sc->sc_dev), 595 prop_dictionary_get_bool(device_properties(sc->sc_dev),
587 "is_swapped", &is_swapped); 596 "is_swapped", &is_swapped);
588 597
589 if (is_bgr) { 598 if (is_bgr) {
590 /* someone requested BGR */ 599 /* someone requested BGR */
591 ri->ri_rpos = 0; 600 ri->ri_rpos = 0;
592 ri->ri_gpos = 8; 601 ri->ri_gpos = 8;
593 ri->ri_bpos = 16; 602 ri->ri_bpos = 16;
594 } else if (is_swapped) { 603 } else if (is_swapped) {
595 /* byte-swapped, must be 32 bpp */ 604 /* byte-swapped, must be 32 bpp */
596 KASSERT(ri->ri_depth == 32); 605 KASSERT(ri->ri_depth == 32);
597 ri->ri_rpos = 8; 606 ri->ri_rpos = 8;
598 ri->ri_gpos = 16; 607 ri->ri_gpos = 16;
599 ri->ri_bpos = 24; 608 ri->ri_bpos = 24;
600 } else { 609 } else {
601 /* assume RGB */ 610 /* assume RGB */
602 ri->ri_rpos = 16; 611 ri->ri_rpos = 16;
603 ri->ri_gpos = 8; 612 ri->ri_gpos = 8;
604 ri->ri_bpos = 0; 613 ri->ri_bpos = 0;
605 } 614 }
606 break; 615 break;
607 616
608 case 16: 617 case 16:
609 case 15: 618 case 15:
610 ri->ri_flg |= RI_ENABLE_ALPHA; 619 ri->ri_flg |= RI_ENABLE_ALPHA;
611 break; 620 break;
612 621
613 case 8: 622 case 8:
614 if (sc->sc_cmcb != NULL) 623 if (sc->sc_cmcb != NULL)
615 ri->ri_flg |= RI_ENABLE_ALPHA | RI_8BIT_IS_RGB; 624 ri->ri_flg |= RI_ENABLE_ALPHA | RI_8BIT_IS_RGB;
616 break; 625 break;
617 626
618 case 2: 627 case 2:
619 ri->ri_flg |= RI_ENABLE_ALPHA; 628 ri->ri_flg |= RI_ENABLE_ALPHA;
620 break; 629 break;
621 630
622 default: 631 default:
623 break; 632 break;
624 } 633 }
625 634
626 wantcols = genfb_calc_cols(sc); 635 wantcols = genfb_calc_cols(sc);
627 636
628 rasops_init(ri, 0, wantcols); 637 rasops_init(ri, 0, wantcols);
629 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 638 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
630 WSSCREEN_RESIZE; 639 WSSCREEN_RESIZE;
631 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 640 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
632 sc->sc_width / ri->ri_font->fontwidth); 641 sc->sc_width / ri->ri_font->fontwidth);
633 642
634 ri->ri_hw = scr; 643 ri->ri_hw = scr;
635 644#if GENFB_GLYPHCACHE > 0
 645 sc->sc_putchar = ri->ri_ops.putchar;
 646 ri->ri_ops.putchar = genfb_putchar;
 647#endif
636#ifdef GENFB_DISABLE_TEXT 648#ifdef GENFB_DISABLE_TEXT
637 if (scr == &sc->sc_console_screen && !DISABLESPLASH) 649 if (scr == &sc->sc_console_screen && !DISABLESPLASH)
638 SCREEN_DISABLE_DRAWING(&sc->sc_console_screen); 650 SCREEN_DISABLE_DRAWING(&sc->sc_console_screen);
639#endif 651#endif
640} 652}
641 653
642/* Returns the width of the display in millimeters, or 0 if not known. */ 654/* Returns the width of the display in millimeters, or 0 if not known. */
643static int 655static int
644genfb_calc_hsize(struct genfb_softc *sc) 656genfb_calc_hsize(struct genfb_softc *sc)
645{ 657{
646 device_t dev = sc->sc_dev; 658 device_t dev = sc->sc_dev;
647 prop_dictionary_t dict = device_properties(dev); 659 prop_dictionary_t dict = device_properties(dev);
648 prop_data_t edid_data; 660 prop_data_t edid_data;
649 struct edid_info *edid; 661 struct edid_info *edid;
650 const char *edid_ptr; 662 const char *edid_ptr;
651 int hsize; 663 int hsize;
652 664
653 edid_data = prop_dictionary_get(dict, "EDID"); 665 edid_data = prop_dictionary_get(dict, "EDID");
654 if (edid_data == NULL || prop_data_size(edid_data) < 128) 666 if (edid_data == NULL || prop_data_size(edid_data) < 128)
655 return 0; 667 return 0;
656 668
657 edid = kmem_alloc(sizeof(*edid), KM_SLEEP); 669 edid = kmem_alloc(sizeof(*edid), KM_SLEEP);
658 670
659 edid_ptr = prop_data_value(edid_data); 671 edid_ptr = prop_data_value(edid_data);
660 if (edid_parse(__UNCONST(edid_ptr), edid) == 0) 672 if (edid_parse(__UNCONST(edid_ptr), edid) == 0)
661 hsize = (int)edid->edid_max_hsize * 10; 673 hsize = (int)edid->edid_max_hsize * 10;
662 else 674 else
663 hsize = 0; 675 hsize = 0;
664 676
665 kmem_free(edid, sizeof(*edid)); 677 kmem_free(edid, sizeof(*edid));
666 678
667 return hsize; 679 return hsize;
668} 680}
669 681
670/* Return the minimum number of character columns based on DPI */ 682/* Return the minimum number of character columns based on DPI */
671static int 683static int
672genfb_calc_cols(struct genfb_softc *sc) 684genfb_calc_cols(struct genfb_softc *sc)
673{ 685{
674 const int hsize = genfb_calc_hsize(sc); 686 const int hsize = genfb_calc_hsize(sc);
675 687
676 return MAX(RASOPS_DEFAULT_WIDTH, hsize / GENFB_CHAR_WIDTH_MM); 688 return MAX(RASOPS_DEFAULT_WIDTH, hsize / GENFB_CHAR_WIDTH_MM);
677} 689}
678 690
679static int 691static int
680genfb_putcmap(struct genfb_softc *sc, struct wsdisplay_cmap *cm) 692genfb_putcmap(struct genfb_softc *sc, struct wsdisplay_cmap *cm)
681{ 693{
682 u_char *r, *g, *b; 694 u_char *r, *g, *b;
683 u_int index = cm->index; 695 u_int index = cm->index;
684 u_int count = cm->count; 696 u_int count = cm->count;
685 int i, error; 697 int i, error;
686 u_char rbuf[256], gbuf[256], bbuf[256]; 698 u_char rbuf[256], gbuf[256], bbuf[256];
687 699
688#ifdef GENFB_DEBUG 700#ifdef GENFB_DEBUG
689 aprint_debug("putcmap: %d %d\n",index, count); 701 aprint_debug("putcmap: %d %d\n",index, count);
690#endif 702#endif
691 if (index >= 256 || count > 256 || index + count > 256) 703 if (index >= 256 || count > 256 || index + count > 256)
692 return EINVAL; 704 return EINVAL;
693 705
694 error = copyin(cm->red, &rbuf[index], count); 706 error = copyin(cm->red, &rbuf[index], count);
695 if (error) 707 if (error)
696 return error; 708 return error;
697 error = copyin(cm->green, &gbuf[index], count); 709 error = copyin(cm->green, &gbuf[index], count);
698 if (error) 710 if (error)
699 return error; 711 return error;
700 error = copyin(cm->blue, &bbuf[index], count); 712 error = copyin(cm->blue, &bbuf[index], count);
701 if (error) 713 if (error)
702 return error; 714 return error;
703 715
704 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 716 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
705 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 717 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
706 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 718 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
707 719
708 r = &sc->sc_cmap_red[index]; 720 r = &sc->sc_cmap_red[index];
709 g = &sc->sc_cmap_green[index]; 721 g = &sc->sc_cmap_green[index];
710 b = &sc->sc_cmap_blue[index]; 722 b = &sc->sc_cmap_blue[index];
711 723
712 for (i = 0; i < count; i++) { 724 for (i = 0; i < count; i++) {
713 genfb_putpalreg(sc, index, *r, *g, *b); 725 genfb_putpalreg(sc, index, *r, *g, *b);
714 index++; 726 index++;
715 r++, g++, b++; 727 r++, g++, b++;
716 } 728 }
717 return 0; 729 return 0;
718} 730}
719 731
720static int 732static int
721genfb_getcmap(struct genfb_softc *sc, struct wsdisplay_cmap *cm) 733genfb_getcmap(struct genfb_softc *sc, struct wsdisplay_cmap *cm)
722{ 734{
723 u_int index = cm->index; 735 u_int index = cm->index;
724 u_int count = cm->count; 736 u_int count = cm->count;
725 int error; 737 int error;
726 738
727 if (index >= 256 || count > 256 || index + count > 256) 739 if (index >= 256 || count > 256 || index + count > 256)
728 return EINVAL; 740 return EINVAL;
729 741
730 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 742 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
731 if (error) 743 if (error)
732 return error; 744 return error;
733 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 745 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
734 if (error) 746 if (error)
735 return error; 747 return error;
736 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 748 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
737 if (error) 749 if (error)
738 return error; 750 return error;
739 751
740 return 0; 752 return 0;
741} 753}
742 754
743void 755void
744genfb_restore_palette(struct genfb_softc *sc) 756genfb_restore_palette(struct genfb_softc *sc)
745{ 757{
746 int i; 758 int i;
747 759
748 if (sc->sc_depth <= 8) { 760 if (sc->sc_depth <= 8) {
749 for (i = 0; i < (1 << sc->sc_depth); i++) { 761 for (i = 0; i < (1 << sc->sc_depth); i++) {
750 genfb_putpalreg(sc, i, sc->sc_cmap_red[i], 762 genfb_putpalreg(sc, i, sc->sc_cmap_red[i],
751 sc->sc_cmap_green[i], sc->sc_cmap_blue[i]); 763 sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
752 } 764 }
753 } 765 }
754} 766}
755 767
756static void 768static void
757genfb_init_palette(struct genfb_softc *sc) 769genfb_init_palette(struct genfb_softc *sc)
758{ 770{
759 int i, j, tmp; 771 int i, j, tmp;
760 772
761 if (sc->sc_depth == 8) { 773 if (sc->sc_depth == 8) {
762 /* generate an r3g3b2 colour map */ 774 /* generate an r3g3b2 colour map */
763 for (i = 0; i < 256; i++) { 775 for (i = 0; i < 256; i++) {
764 tmp = i & 0xe0; 776 tmp = i & 0xe0;
765 /* 777 /*
766 * replicate bits so 0xe0 maps to a red value of 0xff 778 * replicate bits so 0xe0 maps to a red value of 0xff
767 * in order to make white look actually white 779 * in order to make white look actually white
768 */ 780 */
769 tmp |= (tmp >> 3) | (tmp >> 6); 781 tmp |= (tmp >> 3) | (tmp >> 6);
770 sc->sc_cmap_red[i] = tmp; 782 sc->sc_cmap_red[i] = tmp;
771 783
772 tmp = (i & 0x1c) << 3; 784 tmp = (i & 0x1c) << 3;
773 tmp |= (tmp >> 3) | (tmp >> 6); 785 tmp |= (tmp >> 3) | (tmp >> 6);
774 sc->sc_cmap_green[i] = tmp; 786 sc->sc_cmap_green[i] = tmp;
775 787
776 tmp = (i & 0x03) << 6; 788 tmp = (i & 0x03) << 6;
777 tmp |= tmp >> 2; 789 tmp |= tmp >> 2;
778 tmp |= tmp >> 4; 790 tmp |= tmp >> 4;
779 sc->sc_cmap_blue[i] = tmp; 791 sc->sc_cmap_blue[i] = tmp;
780 792
781 genfb_putpalreg(sc, i, sc->sc_cmap_red[i], 793 genfb_putpalreg(sc, i, sc->sc_cmap_red[i],
782 sc->sc_cmap_green[i], 794 sc->sc_cmap_green[i],
783 sc->sc_cmap_blue[i]); 795 sc->sc_cmap_blue[i]);
784 } 796 }
785 } else { 797 } else {
786 /* steal rasops' ANSI cmap */ 798 /* steal rasops' ANSI cmap */
787 j = 0; 799 j = 0;
788 for (i = 0; i < 256; i++) { 800 for (i = 0; i < 256; i++) {
789 sc->sc_cmap_red[i] = rasops_cmap[j]; 801 sc->sc_cmap_red[i] = rasops_cmap[j];
790 sc->sc_cmap_green[i] = rasops_cmap[j + 1]; 802 sc->sc_cmap_green[i] = rasops_cmap[j + 1];
791 sc->sc_cmap_blue[i] = rasops_cmap[j + 2]; 803 sc->sc_cmap_blue[i] = rasops_cmap[j + 2];
792 j += 3; 804 j += 3;
793 } 805 }
794 } 806 }
795} 807}
796 808
797static int 809static int
798genfb_putpalreg(struct genfb_softc *sc, uint8_t idx, uint8_t r, uint8_t g, 810genfb_putpalreg(struct genfb_softc *sc, uint8_t idx, uint8_t r, uint8_t g,
799 uint8_t b) 811 uint8_t b)
800{ 812{
801 813
802 if (sc->sc_cmcb) { 814 if (sc->sc_cmcb) {
803 815
804 sc->sc_cmcb->gcc_set_mapreg(sc->sc_cmcb->gcc_cookie, 816 sc->sc_cmcb->gcc_set_mapreg(sc->sc_cmcb->gcc_cookie,
805 idx, r, g, b); 817 idx, r, g, b);
806 } 818 }
807 return 0; 819 return 0;
808} 820}
809 821
810void 822void
811genfb_cnattach(void) 823genfb_cnattach(void)
812{ 824{
813 genfb_cnattach_called = 1; 825 genfb_cnattach_called = 1;
814} 826}
815 827
816void 828void
817genfb_disable(void) 829genfb_disable(void)
818{ 830{
819 genfb_enabled = 0; 831 genfb_enabled = 0;
820} 832}
821 833
822int 834int
823genfb_is_console(void) 835genfb_is_console(void)
824{ 836{
825 return genfb_cnattach_called; 837 return genfb_cnattach_called;
826} 838}
827 839
828int 840int
829genfb_is_enabled(void) 841genfb_is_enabled(void)
830{ 842{
831 return genfb_enabled; 843 return genfb_enabled;
832} 844}
833 845
834int 846int
835genfb_borrow(bus_addr_t addr, bus_space_handle_t *hdlp) 847genfb_borrow(bus_addr_t addr, bus_space_handle_t *hdlp)
836{ 848{
837 struct genfb_softc *sc = genfb_softc; 849 struct genfb_softc *sc = genfb_softc;
838 850
839 if (sc && sc->sc_ops.genfb_borrow) 851 if (sc && sc->sc_ops.genfb_borrow)
840 return sc->sc_ops.genfb_borrow(sc, addr, hdlp); 852 return sc->sc_ops.genfb_borrow(sc, addr, hdlp);
841 return 0; 853 return 0;
842} 854}
843 855
844static void 856static void
845genfb_brightness_up(device_t dev) 857genfb_brightness_up(device_t dev)
846{ 858{
847 struct genfb_softc *sc = device_private(dev); 859 struct genfb_softc *sc = device_private(dev);
848 860
849 KASSERT(sc->sc_brightness != NULL && 861 KASSERT(sc->sc_brightness != NULL &&
850 sc->sc_brightness->gpc_upd_parameter != NULL); 862 sc->sc_brightness->gpc_upd_parameter != NULL);
851 863
852 (void)sc->sc_brightness->gpc_upd_parameter( 864 (void)sc->sc_brightness->gpc_upd_parameter(
853 sc->sc_brightness->gpc_cookie, GENFB_BRIGHTNESS_STEP); 865 sc->sc_brightness->gpc_cookie, GENFB_BRIGHTNESS_STEP);
854} 866}
855 867
856static void 868static void
857genfb_brightness_down(device_t dev) 869genfb_brightness_down(device_t dev)
858{ 870{
859 struct genfb_softc *sc = device_private(dev); 871 struct genfb_softc *sc = device_private(dev);
860 872
861 KASSERT(sc->sc_brightness != NULL && 873 KASSERT(sc->sc_brightness != NULL &&
862 sc->sc_brightness->gpc_upd_parameter != NULL); 874 sc->sc_brightness->gpc_upd_parameter != NULL);
863 875
864 (void)sc->sc_brightness->gpc_upd_parameter( 876 (void)sc->sc_brightness->gpc_upd_parameter(
865 sc->sc_brightness->gpc_cookie, - GENFB_BRIGHTNESS_STEP); 877 sc->sc_brightness->gpc_cookie, - GENFB_BRIGHTNESS_STEP);
866} 878}
867 879
868void 880void
869genfb_enable_polling(device_t dev) 881genfb_enable_polling(device_t dev)
870{ 882{
871 struct genfb_softc *sc = device_private(dev); 883 struct genfb_softc *sc = device_private(dev);
872 884
873 if (sc->sc_console_screen.scr_vd) { 885 if (sc->sc_console_screen.scr_vd) {
874 SCREEN_ENABLE_DRAWING(&sc->sc_console_screen); 886 SCREEN_ENABLE_DRAWING(&sc->sc_console_screen);
875 vcons_hard_switch(&sc->sc_console_screen); 887 vcons_hard_switch(&sc->sc_console_screen);
876 vcons_enable_polling(&sc->vd); 888 vcons_enable_polling(&sc->vd);
877 if (sc->sc_ops.genfb_enable_polling) 889 if (sc->sc_ops.genfb_enable_polling)
878 (*sc->sc_ops.genfb_enable_polling)(sc); 890 (*sc->sc_ops.genfb_enable_polling)(sc);
879 } 891 }
880} 892}
881 893
882void 894void
883genfb_disable_polling(device_t dev) 895genfb_disable_polling(device_t dev)
884{ 896{
885 struct genfb_softc *sc = device_private(dev); 897 struct genfb_softc *sc = device_private(dev);
886 898
887 if (sc->sc_console_screen.scr_vd) { 899 if (sc->sc_console_screen.scr_vd) {
888 if (sc->sc_ops.genfb_disable_polling) 900 if (sc->sc_ops.genfb_disable_polling)
889 (*sc->sc_ops.genfb_disable_polling)(sc); 901 (*sc->sc_ops.genfb_disable_polling)(sc);
890 vcons_disable_polling(&sc->vd); 902 vcons_disable_polling(&sc->vd);
891 } 903 }
892} 904}
 905
 906#if GENFB_GLYPHCACHE > 0
 907#define GLYPHCACHESIZE ((GENFB_GLYPHCACHE) * 1024 * 1024)
 908
 909static inline int
 910attr2idx(long attr)
 911{
 912 if ((attr & 0xf0f00ff8) != 0)
 913 return -1;
 914
 915 return (((attr >> 16) & 0x0f) | ((attr >> 20) & 0xf0));
 916}
 917
 918static int
 919genfb_setup_glyphcache(struct genfb_softc *sc, long defattr)
 920{
 921 struct rasops_info *ri = &sc->sc_console_screen.scr_ri,
 922 *cri = &sc->sc_cache_ri;
 923 gc_bucket *b;
 924 int i, usedcells = 0, idx, j;
 925
 926 sc->sc_cache = kmem_alloc(GLYPHCACHESIZE, KM_SLEEP);
 927
 928 /*
 929 * now we build a mutant rasops_info for the cache - same pixel type
 930 * and such as the real fb, but only one character per line for
 931 * simplicity and locality
 932 */
 933 memcpy(cri, ri, sizeof(struct rasops_info));
 934 cri->ri_ops.putchar = sc->sc_putchar;
 935 cri->ri_width = ri->ri_font->fontwidth;
 936 cri->ri_stride = ri->ri_xscale;
 937 cri->ri_bits = sc->sc_cache;
 938 cri->ri_hwbits = NULL;
 939 cri->ri_origbits = sc->sc_cache;
 940 cri->ri_cols = 1;
 941 cri->ri_rows = GLYPHCACHESIZE /
 942 (cri->ri_stride * cri->ri_font->fontheight);
 943 cri->ri_xorigin = 0;
 944 cri->ri_yorigin = 0;
 945 cri->ri_xscale = ri->ri_xscale;
 946 cri->ri_yscale = ri->ri_font->fontheight * ri->ri_xscale;
 947
 948 printf("size %d %d %d\n", GLYPHCACHESIZE, ri->ri_width, ri->ri_stride);
 949 printf("cells: %d\n", cri->ri_rows);
 950 sc->sc_nbuckets = uimin(256, cri->ri_rows / 223);
 951 sc->sc_buckets = kmem_alloc(sizeof(gc_bucket) * sc->sc_nbuckets, KM_SLEEP);
 952 printf("buckets: %d\n", sc->sc_nbuckets);
 953 for (i = 0; i < sc->sc_nbuckets; i++) {
 954 b = &sc->sc_buckets[i];
 955 b->gb_firstcell = usedcells;
 956 b->gb_numcells = uimin(223, cri->ri_rows - usedcells);
 957 usedcells += 223;
 958 b->gb_usedcells = 0;
 959 b->gb_index = -1;
 960 for (j = 0; j < 223; j++) b->gb_map[j] = -1;
 961 }
 962
 963 /* initialize the attribute map... */
 964 for (i = 0; i < 256; i++) {
 965 sc->sc_attrmap[i] = -1;
 966 }
 967
 968 /* first bucket goes to default attr */
 969 idx = attr2idx(defattr);
 970 printf("defattr %08lx idx %x\n", defattr, idx);
 971
 972 if (idx >= 0) {
 973 sc->sc_attrmap[idx] = 0;
 974 sc->sc_buckets[0].gb_index = idx;
 975 }
 976
 977 return 0;
 978}
 979
 980static void
 981genfb_putchar(void *cookie, int row, int col, u_int c, long attr)
 982{
 983 struct rasops_info *ri = cookie;
 984 struct vcons_screen *scr = ri->ri_hw;
 985 struct genfb_softc *sc = scr->scr_cookie;
 986 uint8_t *src, *dst;
 987 gc_bucket *b;
 988 int i, idx, bi, cell;
 989
 990 attr &= ~WSATTR_USERMASK;
 991
 992 idx = attr2idx(attr);
 993 if (c < 33 || c > 255 || idx < 0) goto nope;
 994
 995 /* look for a bucket with the right attribute */
 996 bi = sc->sc_attrmap[idx];
 997 if (bi == -1) {
 998 /* nope, see if there's an empty one left */
 999 bi = 1;
 1000 while ((bi < sc->sc_nbuckets) &&
 1001 (sc->sc_buckets[bi].gb_index != -1)) {
 1002 bi++;
 1003 }
 1004 if (bi < sc->sc_nbuckets) {
 1005 /* found one -> grab it */
 1006 sc->sc_attrmap[idx] = bi;
 1007 b = &sc->sc_buckets[bi];
 1008 b->gb_index = idx;
 1009 b->gb_usedcells = 0;
 1010 /* make sure this doesn't get evicted right away */
 1011 b->gb_lastread = time_uptime;
 1012 } else {
 1013 /*
 1014 * still nothing
 1015 * steal the least recently read bucket
 1016 */
 1017 time_t moo = time_uptime;
 1018 int oldest = 1;
 1019
 1020 for (i = 1; i < sc->sc_nbuckets; i++) {
 1021 if (sc->sc_buckets[i].gb_lastread < moo) {
 1022 oldest = i;
 1023 moo = sc->sc_buckets[i].gb_lastread;
 1024 }
 1025 }
 1026
 1027 /* if we end up here all buckets must be in use */
 1028 b = &sc->sc_buckets[oldest];
 1029 sc->sc_attrmap[b->gb_index] = -1;
 1030 b->gb_index = idx;
 1031 b->gb_usedcells = 0;
 1032 sc->sc_attrmap[idx] = oldest;
 1033 /* now scrub it */
 1034 for (i = 0; i < 223; i++)
 1035 b->gb_map[i] = -1;
 1036 /* and set the time stamp */
 1037 b->gb_lastread = time_uptime;
 1038 }
 1039 } else {
 1040 /* found one */
 1041 b = &sc->sc_buckets[bi];
 1042 }
 1043
 1044 /* see if there's room in the bucket */
 1045 if (b->gb_usedcells >= b->gb_numcells) goto nope;
 1046
 1047 cell = b->gb_map[c - 33];
 1048 if (cell == -1) {
 1049 if (b->gb_usedcells >= b->gb_numcells)
 1050 goto nope;
 1051 cell = atomic_add_int_nv(&b->gb_usedcells, 1) - 1;
 1052 b->gb_map[c - 33] = cell;
 1053 cell += b->gb_firstcell;
 1054 sc->sc_putchar(&sc->sc_cache_ri, cell, 0, c, attr);
 1055
 1056 } else
 1057 cell += b->gb_firstcell;
 1058
 1059 src = sc->sc_cache + cell * sc->sc_cache_ri.ri_yscale;
 1060 dst = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
 1061 for (i = 0; i < ri->ri_font->fontheight; i++) {
 1062 memcpy(dst, src, ri->ri_xscale);
 1063 src += ri->ri_xscale;
 1064 dst += ri->ri_stride;
 1065 }
 1066 b->gb_lastread = time_uptime;
 1067 return;
 1068nope:
 1069 sc->sc_putchar(cookie, row, col, c, attr);
 1070}
 1071
 1072#endif

cvs diff -r1.25 -r1.26 src/sys/dev/wsfb/genfbvar.h (switch to unified diff)

--- src/sys/dev/wsfb/genfbvar.h 2017/02/25 01:11:55 1.25
+++ src/sys/dev/wsfb/genfbvar.h 2021/01/27 22:42:53 1.26
@@ -1,141 +1,180 @@ @@ -1,141 +1,180 @@
1/* $NetBSD: genfbvar.h,v 1.25 2017/02/25 01:11:55 nonaka Exp $ */ 1/* $NetBSD: genfbvar.h,v 1.26 2021/01/27 22:42:53 macallan Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2007 Michael Lorenz 4 * Copyright (c) 2007 Michael Lorenz
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#ifndef GENFBVAR_H 29#ifndef GENFBVAR_H
30#define GENFBVAR_H 30#define GENFBVAR_H
31 31
32#ifdef _KERNEL_OPT 32#ifdef _KERNEL_OPT
33#include "opt_splash.h" 33#include "opt_splash.h"
34#endif 34#endif
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/buf.h> 37#include <sys/buf.h>
38#include <sys/conf.h> 38#include <sys/conf.h>
39#include <sys/device.h> 39#include <sys/device.h>
40 40
41#include <sys/bus.h> 41#include <sys/bus.h>
42 42
43#include <dev/wscons/wsconsio.h> 43#include <dev/wscons/wsconsio.h>
44#include <dev/wscons/wsdisplayvar.h> 44#include <dev/wscons/wsdisplayvar.h>
45#include <dev/rasops/rasops.h> 45#include <dev/rasops/rasops.h>
46 46
47#include <dev/wscons/wsdisplay_vconsvar.h> 47#include <dev/wscons/wsdisplay_vconsvar.h>
48#ifdef _KERNEL_OPT 48#ifdef _KERNEL_OPT
49#include "opt_genfb.h" 49#include "opt_genfb.h"
50#endif 50#endif
51 51
52#ifdef SPLASHSCREEN 52#ifdef SPLASHSCREEN
53#define GENFB_DISABLE_TEXT 53#define GENFB_DISABLE_TEXT
54#include <dev/splash/splash.h> 54#include <dev/splash/splash.h>
55#endif 55#endif
56 56
 57#if GENFB_GLYPHCACHE > 0
 58#include <dev/wscons/wsdisplay_glyphcachevar.h>
 59#endif
 60
57struct genfb_softc; 61struct genfb_softc;
58 62
59struct genfb_ops { 63struct genfb_ops {
60 int (*genfb_ioctl)(void *, void *, u_long, void *, int, struct lwp *); 64 int (*genfb_ioctl)(void *, void *, u_long, void *, int, struct lwp *);
61 paddr_t (*genfb_mmap)(void *, void *, off_t, int); 65 paddr_t (*genfb_mmap)(void *, void *, off_t, int);
62 int (*genfb_borrow)(void *, bus_addr_t, bus_space_handle_t *); 66 int (*genfb_borrow)(void *, bus_addr_t, bus_space_handle_t *);
63 int (*genfb_enable_polling)(void *); 67 int (*genfb_enable_polling)(void *);
64 int (*genfb_disable_polling)(void *); 68 int (*genfb_disable_polling)(void *);
65}; 69};
66 70
67struct genfb_colormap_callback { 71struct genfb_colormap_callback {
68 void *gcc_cookie; 72 void *gcc_cookie;
69 void (*gcc_set_mapreg)(void *, int, int, int, int); 73 void (*gcc_set_mapreg)(void *, int, int, int, int);
70}; 74};
71 75
72/* 76/*
73 * Integer parameter provider. Each callback shall return 0 on success, 77 * Integer parameter provider. Each callback shall return 0 on success,
74 * and an error(2) number on failure. The gpc_upd_parameter callback is 78 * and an error(2) number on failure. The gpc_upd_parameter callback is
75 * optional (i.e. it can be NULL). 79 * optional (i.e. it can be NULL).
76 * 80 *
77 * This structure is used for backlight and brightness control. The 81 * This structure is used for backlight and brightness control. The
78 * expected parameter range is: 82 * expected parameter range is:
79 * 83 *
80 * [0, 1] for backlight 84 * [0, 1] for backlight
81 * [0, 255] for brightness 85 * [0, 255] for brightness
82 */ 86 */
83struct genfb_parameter_callback { 87struct genfb_parameter_callback {
84 void *gpc_cookie; 88 void *gpc_cookie;
85 int (*gpc_get_parameter)(void *, int *); 89 int (*gpc_get_parameter)(void *, int *);
86 int (*gpc_set_parameter)(void *, int); 90 int (*gpc_set_parameter)(void *, int);
87 int (*gpc_upd_parameter)(void *, int); 91 int (*gpc_upd_parameter)(void *, int);
88}; 92};
89 93
90struct genfb_pmf_callback { 94struct genfb_pmf_callback {
91 bool (*gpc_suspend)(device_t, const pmf_qual_t *); 95 bool (*gpc_suspend)(device_t, const pmf_qual_t *);
92 bool (*gpc_resume)(device_t, const pmf_qual_t *); 96 bool (*gpc_resume)(device_t, const pmf_qual_t *);
93}; 97};
94 98
95struct genfb_mode_callback { 99struct genfb_mode_callback {
96 bool (*gmc_setmode)(struct genfb_softc *, int); 100 bool (*gmc_setmode)(struct genfb_softc *, int);
97}; 101};
98 102
99struct genfb_softc { 103struct genfb_softc {
100 device_t sc_dev; 104 device_t sc_dev;
101 struct vcons_data vd; 105 struct vcons_data vd;
102 struct genfb_ops sc_ops; 106 struct genfb_ops sc_ops;
103 struct vcons_screen sc_console_screen; 107 struct vcons_screen sc_console_screen;
104 struct wsscreen_descr sc_defaultscreen_descr; 108 struct wsscreen_descr sc_defaultscreen_descr;
105 const struct wsscreen_descr *sc_screens[1]; 109 const struct wsscreen_descr *sc_screens[1];
106 struct wsscreen_list sc_screenlist; 110 struct wsscreen_list sc_screenlist;
107 struct genfb_colormap_callback *sc_cmcb; 111 struct genfb_colormap_callback *sc_cmcb;
108 struct genfb_pmf_callback *sc_pmfcb; 112 struct genfb_pmf_callback *sc_pmfcb;
109 struct genfb_parameter_callback *sc_backlight; 113 struct genfb_parameter_callback *sc_backlight;
110 struct genfb_parameter_callback *sc_brightness; 114 struct genfb_parameter_callback *sc_brightness;
111 struct genfb_mode_callback *sc_modecb; 115 struct genfb_mode_callback *sc_modecb;
112 int sc_backlight_level, sc_backlight_on; 116 int sc_backlight_level, sc_backlight_on;
113 void *sc_fbaddr; /* kva */ 117 void *sc_fbaddr; /* kva */
114 void *sc_shadowfb; 118 void *sc_shadowfb;
115 bool sc_enable_shadowfb; 119 bool sc_enable_shadowfb;
116 bus_addr_t sc_fboffset; /* bus address */ 120 bus_addr_t sc_fboffset; /* bus address */
117 int sc_width, sc_height, sc_stride, sc_depth; 121 int sc_width, sc_height, sc_stride, sc_depth;
118 size_t sc_fbsize; 122 size_t sc_fbsize;
119 int sc_mode; 123 int sc_mode;
120 u_char sc_cmap_red[256]; 124 u_char sc_cmap_red[256];
121 u_char sc_cmap_green[256]; 125 u_char sc_cmap_green[256];
122 u_char sc_cmap_blue[256]; 126 u_char sc_cmap_blue[256];
123 bool sc_want_clear; 127 bool sc_want_clear;
124#ifdef SPLASHSCREEN 128#ifdef SPLASHSCREEN
125 struct splash_info sc_splash; 129 struct splash_info sc_splash;
126#endif 130#endif
127 struct wsdisplay_accessops sc_accessops; 131 struct wsdisplay_accessops sc_accessops;
 132#if GENFB_GLYPHCACHE > 0
 133 /*
 134 * The generic glyphcache code makes a bunch of assumptions that are
 135 * true for most graphics hardware with a directly supported blitter.
 136 * For example it assume that
 137 * - VRAM access from the host is expensive
 138 * - copying data around in VRAM is cheap and can happen in parallel
 139 * to the host CPU
 140 * -> therefore we draw glyphs normally if we have to, so the ( assumed
 141 * to be hardware assisted ) driver supplied putchar() method doesn't
 142 * need to be glyphcache aware, then copy them away for later use
 143 * for genfb things are a bit different. On most hardware:
 144 * - VRAM access from the host is still expensive
 145 * - copying data around in VRAM is also expensive since we don't have
 146 * a blitter and VRAM is mapped uncached
 147 * - VRAM reads are usually slower than writes ( write combining and
 148 * such help writes but not reads, and VRAM might be behind an
 149 * asymmetric bus like AGP ) and must be avoided, both are much
 150 * slower than main memory
 151 * -> therefore we cache glyphs in main memory, no reason to map it
 152 * uncached, we draw into the cache first and then copy the glyph
 153 * into video memory to avoid framebuffer reads and to allow more
 154 * efficient write accesses than putchar() would offer
 155 * Because of this we can't use the generic code but we can recycle a
 156 * few data structures.
 157 */
 158 uint8_t *sc_cache;
 159 struct rasops_info sc_cache_ri;
 160 void (*sc_putchar)(void *, int, int, u_int, long);
 161 int sc_cache_cells;
 162 int sc_nbuckets; /* buckets allocated */
 163 gc_bucket *sc_buckets; /* we allocate as many as we can get into ram */
 164 int sc_attrmap[256]; /* mapping a colour attribute to a bucket */
 165#endif
 166
128}; 167};
129 168
130void genfb_cnattach(void); 169void genfb_cnattach(void);
131void genfb_disable(void); 170void genfb_disable(void);
132int genfb_is_console(void); 171int genfb_is_console(void);
133int genfb_is_enabled(void); 172int genfb_is_enabled(void);
134void genfb_init(struct genfb_softc *); 173void genfb_init(struct genfb_softc *);
135int genfb_attach(struct genfb_softc *, struct genfb_ops *); 174int genfb_attach(struct genfb_softc *, struct genfb_ops *);
136int genfb_borrow(bus_addr_t, bus_space_handle_t *); 175int genfb_borrow(bus_addr_t, bus_space_handle_t *);
137void genfb_restore_palette(struct genfb_softc *); 176void genfb_restore_palette(struct genfb_softc *);
138void genfb_enable_polling(device_t); 177void genfb_enable_polling(device_t);
139void genfb_disable_polling(device_t); 178void genfb_disable_polling(device_t);
140 179
141#endif /* GENFBVAR_H */ 180#endif /* GENFBVAR_H */