diofb.c revision 1.7 1 1.7 thorpej /* $NetBSD: diofb.c,v 1.7 2021/08/07 16:18:53 thorpej Exp $ */
2 1.1 tsutsui /* $OpenBSD: diofb.c,v 1.18 2010/12/26 15:40:59 miod Exp $ */
3 1.1 tsutsui
4 1.1 tsutsui /*
5 1.1 tsutsui * Copyright (c) 2005, Miodrag Vallat
6 1.1 tsutsui *
7 1.1 tsutsui * Redistribution and use in source and binary forms, with or without
8 1.1 tsutsui * modification, are permitted provided that the following conditions
9 1.1 tsutsui * are met:
10 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright
11 1.1 tsutsui * notice, this list of conditions and the following disclaimer.
12 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the
14 1.1 tsutsui * documentation and/or other materials provided with the distribution.
15 1.1 tsutsui *
16 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 1.1 tsutsui * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 1.1 tsutsui * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 1.1 tsutsui * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 1.1 tsutsui * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 1.1 tsutsui * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 1.1 tsutsui * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 1.1 tsutsui * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 1.1 tsutsui * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.1 tsutsui * POSSIBILITY OF SUCH DAMAGE.
27 1.1 tsutsui */
28 1.1 tsutsui /*
29 1.1 tsutsui * Copyright (c) 1988 University of Utah.
30 1.1 tsutsui * Copyright (c) 1990, 1993
31 1.1 tsutsui * The Regents of the University of California. All rights reserved.
32 1.1 tsutsui *
33 1.1 tsutsui * This code is derived from software contributed to Berkeley by
34 1.1 tsutsui * the Systems Programming Group of the University of Utah Computer
35 1.1 tsutsui * Science Department.
36 1.1 tsutsui *
37 1.1 tsutsui * Redistribution and use in source and binary forms, with or without
38 1.1 tsutsui * modification, are permitted provided that the following conditions
39 1.1 tsutsui * are met:
40 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright
41 1.1 tsutsui * notice, this list of conditions and the following disclaimer.
42 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
43 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the
44 1.1 tsutsui * documentation and/or other materials provided with the distribution.
45 1.1 tsutsui * 3. Neither the name of the University nor the names of its contributors
46 1.1 tsutsui * may be used to endorse or promote products derived from this software
47 1.1 tsutsui * without specific prior written permission.
48 1.1 tsutsui *
49 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 1.1 tsutsui * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 1.1 tsutsui * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 1.1 tsutsui * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 1.1 tsutsui * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 1.1 tsutsui * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 1.1 tsutsui * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 1.1 tsutsui * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 1.1 tsutsui * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 1.1 tsutsui * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 1.1 tsutsui * SUCH DAMAGE.
60 1.1 tsutsui */
61 1.1 tsutsui
62 1.1 tsutsui #include <sys/param.h>
63 1.1 tsutsui #include <sys/conf.h>
64 1.1 tsutsui #include <sys/proc.h>
65 1.1 tsutsui #include <sys/ioctl.h>
66 1.1 tsutsui #include <sys/tty.h>
67 1.1 tsutsui #include <sys/systm.h>
68 1.1 tsutsui #include <sys/device.h>
69 1.1 tsutsui #include <sys/bus.h>
70 1.1 tsutsui #include <sys/cpu.h>
71 1.1 tsutsui
72 1.1 tsutsui #include <machine/autoconf.h>
73 1.1 tsutsui
74 1.1 tsutsui #include <dev/wscons/wsconsio.h>
75 1.1 tsutsui #include <dev/wscons/wsdisplayvar.h>
76 1.1 tsutsui #include <dev/rasops/rasops.h>
77 1.1 tsutsui
78 1.1 tsutsui #include <hp300/dev/dioreg.h>
79 1.1 tsutsui #include <hp300/dev/diovar.h>
80 1.1 tsutsui #include <hp300/dev/diofbreg.h>
81 1.1 tsutsui #include <hp300/dev/diofbvar.h>
82 1.1 tsutsui
83 1.2 tsutsui static void diofb_do_cursor(struct rasops_info *);
84 1.2 tsutsui static void diofb_copycols(void *, int, int, int, int);
85 1.2 tsutsui static void diofb_erasecols(void *, int, int, int, long);
86 1.2 tsutsui static void diofb_copyrows(void *, int, int, int);
87 1.2 tsutsui static void diofb_eraserows(void *, int, int, long);
88 1.2 tsutsui static int diofb_allocattr(void *, int, int, int, long *);
89 1.1 tsutsui
90 1.1 tsutsui struct diofb diofb_cn;
91 1.1 tsutsui
92 1.1 tsutsui /*
93 1.1 tsutsui * Frame buffer geometry initialization
94 1.1 tsutsui */
95 1.1 tsutsui
96 1.1 tsutsui int
97 1.1 tsutsui diofb_fbinquire(struct diofb *fb, int scode, struct diofbreg *fbr)
98 1.1 tsutsui {
99 1.1 tsutsui int fboff, regsize;
100 1.1 tsutsui
101 1.1 tsutsui if (ISIIOVA(fbr))
102 1.1 tsutsui fb->regaddr = (uint8_t *)IIOP(fbr);
103 1.1 tsutsui else
104 1.1 tsutsui fb->regaddr = dio_scodetopa(scode);
105 1.1 tsutsui
106 1.1 tsutsui if (fb->fbwidth == 0 || fb->fbheight == 0) {
107 1.1 tsutsui fb->fbwidth = (fbr->fbwmsb << 8) | fbr->fbwlsb;
108 1.1 tsutsui fb->fbheight = (fbr->fbhmsb << 8) | fbr->fbhlsb;
109 1.1 tsutsui }
110 1.1 tsutsui fb->fbsize = fb->fbwidth * fb->fbheight;
111 1.1 tsutsui
112 1.1 tsutsui fb->regkva = (uint8_t *)fbr;
113 1.1 tsutsui fboff = (fbr->fbomsb << 8) | fbr->fbolsb;
114 1.1 tsutsui fb->fbaddr = (uint8_t *) (*((uint8_t *)fbr + fboff) << 16);
115 1.1 tsutsui
116 1.1 tsutsui if (fb->regaddr >= (uint8_t *)DIOII_BASE) {
117 1.1 tsutsui /*
118 1.1 tsutsui * For DIO-II space the fbaddr just computed is
119 1.1 tsutsui * the offset from the select code base (regaddr)
120 1.1 tsutsui * of the framebuffer. Hence it is also implicitly
121 1.1 tsutsui * the size of the set.
122 1.1 tsutsui */
123 1.1 tsutsui regsize = (uintptr_t)fb->fbaddr;
124 1.1 tsutsui fb->fbaddr = fb->regaddr + (uintptr_t)fb->fbaddr;
125 1.1 tsutsui fb->fbkva = (uint8_t *)fbr + regsize;
126 1.1 tsutsui } else {
127 1.1 tsutsui /*
128 1.1 tsutsui * For internal or DIO-I space we need to map the separate
129 1.1 tsutsui * framebuffer.
130 1.1 tsutsui */
131 1.1 tsutsui fb->fbkva = iomap(fb->fbaddr, fb->fbsize);
132 1.1 tsutsui if (fb->fbkva == NULL)
133 1.2 tsutsui return ENOMEM;
134 1.1 tsutsui }
135 1.1 tsutsui if (fb->dwidth == 0 || fb->dheight == 0) {
136 1.1 tsutsui fb->dwidth = (fbr->dwmsb << 8) | fbr->dwlsb;
137 1.1 tsutsui fb->dheight = (fbr->dhmsb << 8) | fbr->dhlsb;
138 1.1 tsutsui }
139 1.1 tsutsui
140 1.1 tsutsui /*
141 1.1 tsutsui * Some displays, such as the DaVinci, appear to return a display
142 1.1 tsutsui * height larger than the frame buffer height.
143 1.1 tsutsui */
144 1.1 tsutsui if (fb->dwidth > fb->fbwidth)
145 1.1 tsutsui fb->dwidth = fb->fbwidth;
146 1.1 tsutsui if (fb->dheight > fb->fbheight)
147 1.1 tsutsui fb->dheight = fb->fbheight;
148 1.1 tsutsui
149 1.5 tsutsui /*
150 1.5 tsutsui * Some displays, such as the HP332 and HP340 internal video
151 1.5 tsutsui * appear to return a display width of 1024 instead of 512.
152 1.5 tsutsui */
153 1.5 tsutsui if (fbr->num_planes == 1 || fbr->num_planes == 4) {
154 1.5 tsutsui if (fb->dwidth == 1024 && fb->dheight == 400)
155 1.5 tsutsui fb->dwidth = 512;
156 1.5 tsutsui }
157 1.5 tsutsui
158 1.1 tsutsui fb->planes = fbr->num_planes;
159 1.1 tsutsui if (fb->planes > 8)
160 1.1 tsutsui fb->planes = 8;
161 1.1 tsutsui fb->planemask = (1 << fb->planes) - 1;
162 1.1 tsutsui
163 1.1 tsutsui fb->mapmode = WSDISPLAYIO_MODE_DUMBFB;
164 1.1 tsutsui
165 1.2 tsutsui return 0;
166 1.1 tsutsui }
167 1.1 tsutsui
168 1.1 tsutsui /*
169 1.1 tsutsui * Frame buffer rasops and colormap setup
170 1.1 tsutsui */
171 1.1 tsutsui
172 1.1 tsutsui void
173 1.1 tsutsui diofb_fbsetup(struct diofb *fb)
174 1.1 tsutsui {
175 1.1 tsutsui struct rasops_info *ri = &fb->ri;
176 1.1 tsutsui
177 1.1 tsutsui /*
178 1.1 tsutsui * Pretend we are an 8bpp frame buffer, unless ri_depth is already
179 1.1 tsutsui * initialized, since this is how it is supposed to be addressed.
180 1.1 tsutsui * (Hyperion forces 1bpp because it is really 1bpp addressed).
181 1.1 tsutsui */
182 1.1 tsutsui if (ri->ri_depth == 0)
183 1.1 tsutsui ri->ri_depth = 8;
184 1.1 tsutsui ri->ri_stride = (fb->fbwidth * ri->ri_depth) / 8;
185 1.1 tsutsui
186 1.1 tsutsui ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
187 1.1 tsutsui /* We don't really support colors on less than 4bpp frame buffers */
188 1.1 tsutsui if (fb->planes < 4)
189 1.1 tsutsui ri->ri_flg |= RI_FORCEMONO;
190 1.1 tsutsui if (fb == &diofb_cn)
191 1.1 tsutsui ri->ri_flg |= RI_NO_AUTO;
192 1.1 tsutsui ri->ri_bits = fb->fbkva;
193 1.1 tsutsui ri->ri_width = fb->dwidth;
194 1.1 tsutsui ri->ri_height = fb->dheight;
195 1.1 tsutsui ri->ri_hw = fb;
196 1.1 tsutsui
197 1.1 tsutsui /*
198 1.1 tsutsui * Ask for an unholy big display, rasops will trim this to more
199 1.1 tsutsui * reasonable values.
200 1.1 tsutsui */
201 1.1 tsutsui rasops_init(ri, 160, 160);
202 1.1 tsutsui
203 1.1 tsutsui diofb_resetcmap(fb);
204 1.1 tsutsui
205 1.1 tsutsui /*
206 1.1 tsutsui * For low depth frame buffers, since we have faked a 8bpp frame buffer
207 1.1 tsutsui * to rasops, we actually have to remove capabilities.
208 1.1 tsutsui */
209 1.1 tsutsui if (fb->planes == 4) {
210 1.1 tsutsui ri->ri_ops.allocattr = diofb_allocattr;
211 1.1 tsutsui ri->ri_caps &= ~WSSCREEN_HILIT;
212 1.1 tsutsui }
213 1.1 tsutsui
214 1.1 tsutsui ri->ri_ops.copycols = diofb_copycols;
215 1.1 tsutsui ri->ri_ops.erasecols = diofb_erasecols;
216 1.1 tsutsui if (ri->ri_depth != 1) {
217 1.1 tsutsui ri->ri_ops.copyrows = diofb_copyrows;
218 1.1 tsutsui ri->ri_ops.eraserows = diofb_eraserows;
219 1.1 tsutsui ri->ri_do_cursor = diofb_do_cursor;
220 1.1 tsutsui }
221 1.1 tsutsui
222 1.1 tsutsui /* Clear entire display, including non visible areas */
223 1.1 tsutsui (*fb->bmv)(fb, 0, 0, 0, 0, fb->fbwidth, fb->fbheight, RR_CLEAR, 0xff);
224 1.1 tsutsui
225 1.1 tsutsui fb->wsd.name = fb->wsdname;
226 1.1 tsutsui fb->wsd.ncols = ri->ri_cols;
227 1.1 tsutsui fb->wsd.nrows = ri->ri_rows;
228 1.1 tsutsui fb->wsd.textops = &ri->ri_ops;
229 1.1 tsutsui fb->wsd.fontwidth = ri->ri_font->fontwidth;
230 1.1 tsutsui fb->wsd.fontheight = ri->ri_font->fontheight;
231 1.1 tsutsui fb->wsd.capabilities = ri->ri_caps;
232 1.1 tsutsui strlcpy(fb->wsdname, "std", sizeof(fb->wsdname));
233 1.1 tsutsui }
234 1.1 tsutsui
235 1.1 tsutsui /*
236 1.1 tsutsui * Setup default emulation mode colormap
237 1.1 tsutsui */
238 1.1 tsutsui void
239 1.1 tsutsui diofb_resetcmap(struct diofb *fb)
240 1.1 tsutsui {
241 1.1 tsutsui const u_char *color;
242 1.1 tsutsui u_int i;
243 1.1 tsutsui
244 1.1 tsutsui /* start with the rasops colormap */
245 1.1 tsutsui color = (const u_char *)rasops_cmap;
246 1.1 tsutsui for (i = 0; i < 256; i++) {
247 1.1 tsutsui fb->cmap.r[i] = *color++;
248 1.1 tsutsui fb->cmap.g[i] = *color++;
249 1.1 tsutsui fb->cmap.b[i] = *color++;
250 1.1 tsutsui }
251 1.1 tsutsui
252 1.1 tsutsui /*
253 1.1 tsutsui * Tweak colormap
254 1.1 tsutsui *
255 1.1 tsutsui * Due to the way rasops cursor work, we need to provide
256 1.1 tsutsui * copies of the 8 or 16 basic colors at extra locations
257 1.1 tsutsui * in 4bpp and 6bpp mode. This is because missing planes
258 1.1 tsutsui * accept writes but read back as zero.
259 1.1 tsutsui *
260 1.1 tsutsui * So, in 6bpp mode:
261 1.1 tsutsui * 00 gets inverted to ff, read back as 3f
262 1.1 tsutsui * 3f gets inverted to c0, read back as 00
263 1.1 tsutsui * and in 4bpp mode:
264 1.1 tsutsui * 00 gets inverted to ff, read back as 0f
265 1.1 tsutsui * 0f gets inverted to f0, read back as 00
266 1.1 tsutsui */
267 1.1 tsutsui
268 1.1 tsutsui switch (fb->planes) {
269 1.1 tsutsui case 6:
270 1.1 tsutsui /*
271 1.1 tsutsui * 00-0f normal colors
272 1.1 tsutsui * 30-3f inverted colors
273 1.1 tsutsui * c0-cf normal colors
274 1.1 tsutsui * f0-ff inverted colors
275 1.1 tsutsui */
276 1.1 tsutsui memcpy(fb->cmap.r + 0xc0, fb->cmap.r + 0x00, 0x10);
277 1.1 tsutsui memcpy(fb->cmap.g + 0xc0, fb->cmap.g + 0x00, 0x10);
278 1.1 tsutsui memcpy(fb->cmap.b + 0xc0, fb->cmap.b + 0x00, 0x10);
279 1.1 tsutsui memcpy(fb->cmap.r + 0x30, fb->cmap.r + 0xf0, 0x10);
280 1.1 tsutsui memcpy(fb->cmap.g + 0x30, fb->cmap.g + 0xf0, 0x10);
281 1.1 tsutsui memcpy(fb->cmap.b + 0x30, fb->cmap.b + 0xf0, 0x10);
282 1.1 tsutsui break;
283 1.1 tsutsui case 4:
284 1.1 tsutsui /*
285 1.1 tsutsui * 00-07 normal colors
286 1.1 tsutsui * 08-0f inverted colors
287 1.1 tsutsui * highlighted colors are not available.
288 1.1 tsutsui */
289 1.1 tsutsui memcpy(fb->cmap.r + 0x08, fb->cmap.r + 0xf8, 0x08);
290 1.1 tsutsui memcpy(fb->cmap.g + 0x08, fb->cmap.g + 0xf8, 0x08);
291 1.1 tsutsui memcpy(fb->cmap.b + 0x08, fb->cmap.b + 0xf8, 0x08);
292 1.1 tsutsui break;
293 1.1 tsutsui }
294 1.1 tsutsui }
295 1.1 tsutsui
296 1.1 tsutsui /*
297 1.1 tsutsui * Attachment helpers
298 1.1 tsutsui */
299 1.1 tsutsui
300 1.1 tsutsui void
301 1.1 tsutsui diofb_cnattach(struct diofb *fb)
302 1.1 tsutsui {
303 1.1 tsutsui long defattr;
304 1.1 tsutsui struct rasops_info *ri;
305 1.1 tsutsui
306 1.1 tsutsui ri = &fb->ri;
307 1.1 tsutsui ri->ri_ops.allocattr(ri, 0, 0, 0, &defattr);
308 1.1 tsutsui wsdisplay_cnattach(&fb->wsd, ri, 0, 0, defattr);
309 1.1 tsutsui }
310 1.1 tsutsui
311 1.1 tsutsui void
312 1.1 tsutsui diofb_end_attach(device_t self, struct wsdisplay_accessops *accessops,
313 1.1 tsutsui struct diofb *fb, int console, const char *descr)
314 1.1 tsutsui {
315 1.1 tsutsui struct wsemuldisplaydev_attach_args waa;
316 1.1 tsutsui
317 1.3 tsutsui aprint_normal(": %dx%d", fb->dwidth, fb->dheight);
318 1.1 tsutsui
319 1.1 tsutsui if (fb->planes == 1)
320 1.3 tsutsui aprint_normal(" monochrome");
321 1.1 tsutsui else
322 1.3 tsutsui aprint_normal("x%d", fb->planes);
323 1.1 tsutsui
324 1.1 tsutsui if (descr != NULL)
325 1.3 tsutsui aprint_normal(" %s", descr);
326 1.3 tsutsui aprint_normal(" frame buffer\n");
327 1.1 tsutsui
328 1.1 tsutsui fb->scrlist[0] = &fb->wsd;
329 1.1 tsutsui fb->wsl.nscreens = 1;
330 1.4 christos fb->wsl.screens = (void *)fb->scrlist;
331 1.1 tsutsui
332 1.1 tsutsui waa.console = console;
333 1.1 tsutsui waa.scrdata = &fb->wsl;
334 1.1 tsutsui waa.accessops = accessops;
335 1.1 tsutsui waa.accesscookie = fb;
336 1.1 tsutsui
337 1.7 thorpej config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE);
338 1.1 tsutsui }
339 1.1 tsutsui
340 1.1 tsutsui /*
341 1.1 tsutsui * Common wsdisplay emulops for DIO frame buffers
342 1.1 tsutsui */
343 1.1 tsutsui
344 1.1 tsutsui int
345 1.1 tsutsui diofb_allocattr(void *cookie, int fg, int bg, int flg, long *attr)
346 1.1 tsutsui {
347 1.2 tsutsui
348 1.1 tsutsui if ((flg & (WSATTR_BLINK | WSATTR_HILIT)) != 0)
349 1.2 tsutsui return EINVAL;
350 1.1 tsutsui
351 1.1 tsutsui if ((flg & WSATTR_WSCOLORS) == 0) {
352 1.1 tsutsui fg = WSCOL_WHITE;
353 1.1 tsutsui bg = WSCOL_BLACK;
354 1.1 tsutsui }
355 1.1 tsutsui
356 1.1 tsutsui if ((flg & WSATTR_REVERSE) != 0) {
357 1.1 tsutsui int swap;
358 1.1 tsutsui swap = fg;
359 1.1 tsutsui fg = bg;
360 1.1 tsutsui bg = swap;
361 1.1 tsutsui }
362 1.1 tsutsui
363 1.1 tsutsui flg = ((flg & WSATTR_UNDERLINE) ? 1 : 0);
364 1.1 tsutsui
365 1.1 tsutsui *attr = (bg << 16) | (fg << 24) | flg;
366 1.1 tsutsui
367 1.1 tsutsui return 0;
368 1.1 tsutsui }
369 1.1 tsutsui
370 1.1 tsutsui void
371 1.1 tsutsui diofb_copycols(void *cookie, int row, int src, int dst, int n)
372 1.1 tsutsui {
373 1.1 tsutsui struct rasops_info *ri = cookie;
374 1.1 tsutsui struct diofb *fb = ri->ri_hw;
375 1.1 tsutsui
376 1.1 tsutsui n *= ri->ri_font->fontwidth;
377 1.1 tsutsui src *= ri->ri_font->fontwidth;
378 1.1 tsutsui dst *= ri->ri_font->fontwidth;
379 1.1 tsutsui row *= ri->ri_font->fontheight;
380 1.1 tsutsui
381 1.1 tsutsui (*fb->bmv)(fb, ri->ri_xorigin + src, ri->ri_yorigin + row,
382 1.1 tsutsui ri->ri_xorigin + dst, ri->ri_yorigin + row,
383 1.1 tsutsui n, ri->ri_font->fontheight, RR_COPY, 0xff);
384 1.1 tsutsui }
385 1.1 tsutsui
386 1.1 tsutsui void
387 1.1 tsutsui diofb_copyrows(void *cookie, int src, int dst, int n)
388 1.1 tsutsui {
389 1.1 tsutsui struct rasops_info *ri = cookie;
390 1.1 tsutsui struct diofb *fb = ri->ri_hw;
391 1.1 tsutsui
392 1.1 tsutsui n *= ri->ri_font->fontheight;
393 1.1 tsutsui src *= ri->ri_font->fontheight;
394 1.1 tsutsui dst *= ri->ri_font->fontheight;
395 1.1 tsutsui
396 1.1 tsutsui (*fb->bmv)(fb, ri->ri_xorigin, ri->ri_yorigin + src,
397 1.1 tsutsui ri->ri_xorigin, ri->ri_yorigin + dst,
398 1.1 tsutsui ri->ri_emuwidth, n, RR_COPY, 0xff);
399 1.1 tsutsui }
400 1.1 tsutsui
401 1.1 tsutsui void
402 1.1 tsutsui diofb_erasecols(void *cookie, int row, int col, int num, long attr)
403 1.1 tsutsui {
404 1.1 tsutsui struct rasops_info *ri = cookie;
405 1.1 tsutsui struct diofb *fb = ri->ri_hw;
406 1.1 tsutsui int fg, bg;
407 1.1 tsutsui int snum, scol, srow;
408 1.1 tsutsui
409 1.1 tsutsui rasops_unpack_attr(attr, &fg, &bg, NULL);
410 1.1 tsutsui
411 1.1 tsutsui snum = num * ri->ri_font->fontwidth;
412 1.1 tsutsui scol = col * ri->ri_font->fontwidth + ri->ri_xorigin;
413 1.1 tsutsui srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
414 1.1 tsutsui
415 1.1 tsutsui /*
416 1.1 tsutsui * If this is too tricky for the simple raster ops engine,
417 1.1 tsutsui * pass the fun to rasops.
418 1.1 tsutsui */
419 1.1 tsutsui if ((*fb->bmv)(fb, scol, srow, scol, srow, snum,
420 1.1 tsutsui ri->ri_font->fontheight, RR_CLEAR, 0xff ^ bg) != 0)
421 1.1 tsutsui rasops_erasecols(cookie, row, col, num, attr);
422 1.1 tsutsui }
423 1.1 tsutsui
424 1.1 tsutsui void
425 1.1 tsutsui diofb_eraserows(void *cookie, int row, int num, long attr)
426 1.1 tsutsui {
427 1.1 tsutsui struct rasops_info *ri = cookie;
428 1.1 tsutsui struct diofb *fb = ri->ri_hw;
429 1.1 tsutsui int fg, bg;
430 1.1 tsutsui int srow, snum;
431 1.1 tsutsui int rc;
432 1.1 tsutsui
433 1.1 tsutsui rasops_unpack_attr(attr, &fg, &bg, NULL);
434 1.1 tsutsui bg ^= 0xff;
435 1.1 tsutsui
436 1.1 tsutsui if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) {
437 1.1 tsutsui rc = (*fb->bmv)(fb, 0, 0, 0, 0, ri->ri_width, ri->ri_height,
438 1.1 tsutsui RR_CLEAR, bg);
439 1.1 tsutsui } else {
440 1.1 tsutsui srow = row * ri->ri_font->fontheight + ri->ri_yorigin;
441 1.1 tsutsui snum = num * ri->ri_font->fontheight;
442 1.1 tsutsui rc = (*fb->bmv)(fb, ri->ri_xorigin, srow, ri->ri_xorigin,
443 1.1 tsutsui srow, ri->ri_emuwidth, snum, RR_CLEAR, bg);
444 1.1 tsutsui }
445 1.1 tsutsui if (rc != 0)
446 1.1 tsutsui rasops_eraserows(cookie, row, num, attr);
447 1.1 tsutsui }
448 1.1 tsutsui
449 1.1 tsutsui void
450 1.1 tsutsui diofb_do_cursor(struct rasops_info *ri)
451 1.1 tsutsui {
452 1.1 tsutsui struct diofb *fb = ri->ri_hw;
453 1.1 tsutsui int x, y;
454 1.1 tsutsui
455 1.1 tsutsui x = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
456 1.1 tsutsui y = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
457 1.1 tsutsui (*fb->bmv)(fb, x, y, x, y, ri->ri_font->fontwidth,
458 1.1 tsutsui ri->ri_font->fontheight, RR_INVERT, 0xff);
459 1.1 tsutsui }
460 1.1 tsutsui
461 1.1 tsutsui /*
462 1.1 tsutsui * Common wsdisplay accessops for DIO frame buffers
463 1.1 tsutsui */
464 1.1 tsutsui
465 1.1 tsutsui int
466 1.1 tsutsui diofb_alloc_screen(void *v, const struct wsscreen_descr *type,
467 1.1 tsutsui void **cookiep, int *curxp, int *curyp, long *attrp)
468 1.1 tsutsui {
469 1.1 tsutsui struct diofb *fb = v;
470 1.1 tsutsui struct rasops_info *ri = &fb->ri;
471 1.1 tsutsui
472 1.1 tsutsui if (fb->nscreens > 0)
473 1.2 tsutsui return ENOMEM;
474 1.1 tsutsui
475 1.1 tsutsui *cookiep = ri;
476 1.1 tsutsui *curxp = *curyp = 0;
477 1.1 tsutsui ri->ri_ops.allocattr(ri, 0, 0, 0, attrp);
478 1.1 tsutsui fb->nscreens++;
479 1.1 tsutsui
480 1.2 tsutsui return 0;
481 1.1 tsutsui }
482 1.1 tsutsui
483 1.1 tsutsui void
484 1.1 tsutsui diofb_free_screen(void *v, void *cookie)
485 1.1 tsutsui {
486 1.1 tsutsui struct diofb *fb = v;
487 1.1 tsutsui
488 1.1 tsutsui fb->nscreens--;
489 1.1 tsutsui }
490 1.1 tsutsui
491 1.1 tsutsui int
492 1.1 tsutsui diofb_show_screen(void *v, void *cookie, int waitok,
493 1.1 tsutsui void (*cb)(void *, int, int), void *cbarg)
494 1.1 tsutsui {
495 1.2 tsutsui
496 1.2 tsutsui return 0;
497 1.1 tsutsui }
498 1.1 tsutsui
499 1.1 tsutsui paddr_t
500 1.1 tsutsui diofb_mmap(void *v, void *vs, off_t offset, int prot)
501 1.1 tsutsui {
502 1.1 tsutsui struct diofb *fb = v;
503 1.1 tsutsui
504 1.1 tsutsui if ((offset & PAGE_MASK) != 0)
505 1.2 tsutsui return -1;
506 1.1 tsutsui
507 1.1 tsutsui switch (fb->mapmode) {
508 1.1 tsutsui case WSDISPLAYIO_MODE_MAPPED:
509 1.1 tsutsui if (offset >= 0 && offset < DIOFB_REGSPACE)
510 1.1 tsutsui return m68k_btop(fb->regaddr + offset);
511 1.1 tsutsui offset -= DIOFB_REGSPACE;
512 1.1 tsutsui /* FALLTHROUGH */
513 1.1 tsutsui case WSDISPLAYIO_MODE_DUMBFB:
514 1.1 tsutsui if (offset >= 0 && offset < fb->fbsize)
515 1.1 tsutsui return m68k_btop(fb->fbaddr + offset);
516 1.1 tsutsui break;
517 1.1 tsutsui }
518 1.1 tsutsui
519 1.2 tsutsui return -1;
520 1.1 tsutsui }
521 1.1 tsutsui
522 1.1 tsutsui int
523 1.1 tsutsui diofb_getcmap(struct diofb *fb, struct wsdisplay_cmap *cm)
524 1.1 tsutsui {
525 1.1 tsutsui u_int index = cm->index, count = cm->count;
526 1.1 tsutsui u_int colcount = 1 << fb->planes;
527 1.1 tsutsui int error;
528 1.1 tsutsui
529 1.1 tsutsui if (index >= colcount || count > colcount - index)
530 1.2 tsutsui return EINVAL;
531 1.1 tsutsui
532 1.1 tsutsui if ((error = copyout(fb->cmap.r + index, cm->red, count)) != 0)
533 1.2 tsutsui return error;
534 1.1 tsutsui if ((error = copyout(fb->cmap.g + index, cm->green, count)) != 0)
535 1.2 tsutsui return error;
536 1.1 tsutsui if ((error = copyout(fb->cmap.b + index, cm->blue, count)) != 0)
537 1.2 tsutsui return error;
538 1.1 tsutsui
539 1.2 tsutsui return 0;
540 1.1 tsutsui }
541