vga_raster.c revision 1.2 1 /* $NetBSD: vga_raster.c,v 1.2 2002/10/31 11:05:25 junyoung Exp $ */
2
3 /*
4 * Copyright (c) 2001, 2002 Bang Jun-Young
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
32 * All rights reserved.
33 *
34 * Author: Chris G. Demetriou
35 *
36 * Permission to use, copy, modify and distribute this software and
37 * its documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
44 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie the
54 * rights to redistribute these changes.
55 */
56
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/callout.h>
60 #include <sys/kernel.h>
61 #include <sys/device.h>
62 #include <sys/malloc.h>
63 #include <sys/queue.h>
64 #include <machine/bus.h>
65
66 #include <dev/ic/mc6845reg.h>
67 #include <dev/ic/pcdisplayvar.h>
68 #include <dev/ic/vgareg.h>
69 #include <dev/ic/vgavar.h>
70 #include <dev/ic/videomode.h>
71
72 #include <dev/wscons/wsdisplayvar.h>
73 #include <dev/wscons/wsconsio.h>
74 #include <dev/wsfont/wsfont.h>
75
76 #include <dev/ic/pcdisplay.h>
77
78 u_int8_t builtinfont_data[256 * 16];
79
80 struct wsdisplay_font builtinfont = {
81 "builtin", /* typeface name */
82 0, /* firstchar */
83 256, /* numchars */
84 WSDISPLAY_FONTENC_IBM, /* encoding */
85 8, /* width */
86 16, /* height */
87 1, /* stride */
88 WSDISPLAY_FONTORDER_L2R, /* bit order */
89 WSDISPLAY_FONTORDER_L2R, /* byte order */
90 builtinfont_data /* data */
91 };
92
93 struct vga_scrmem {
94 u_int16_t ch;
95 u_int8_t attr;
96 u_int8_t second; /* XXXBJY should be u_int8_t len; */
97 u_int8_t enc;
98 };
99
100 struct vga_scrmem boot_scrmem[80 * 25];
101
102 struct vga_raster_font {
103 LIST_ENTRY(vga_raster_font) next;
104 struct wsdisplay_font *font;
105 };
106
107 struct vgascreen {
108 LIST_ENTRY(vgascreen) next;
109 struct vga_config *cfg;
110 struct vga_handle *hdl;
111 const struct wsscreen_descr *type;
112
113 int active;
114 struct vga_scrmem *mem;
115 int encoding;
116
117 int dispoffset;
118 int mindispoffset;
119 int maxdispoffset;
120
121 int cursoron; /* Is cursor displayed? */
122 int cursorcol; /* Current cursor column */
123 int cursorrow; /* Current cursor row */
124 struct vga_scrmem cursortmp;
125 int cursorstride;
126
127 LIST_HEAD(, vga_raster_font) fontset;
128 };
129
130 struct vga_moderegs {
131 u_int8_t miscout; /* Misc. output */
132 u_int8_t crtc[VGA_CRTC_NREGS]; /* CRTC controller */
133 u_int8_t atc[VGA_ATC_NREGS]; /* Attribute controller */
134 u_int8_t ts[VGA_TS_NREGS]; /* Time sequencer */
135 u_int8_t gdc[VGA_GDC_NREGS]; /* Graphics display controller */
136 };
137
138 static int vgaconsole, vga_console_type, vga_console_attached;
139 static struct vgascreen vga_console_screen;
140 static struct vga_config vga_console_vc;
141 static struct vga_raster_font vga_console_fontset_ascii;
142 static struct videomode vga_console_modes[2] = {
143 /* 640x400 for 80x25, 80x40 and 80x50 modes */
144 {
145 25175, 640, 664, 760, 800, 400, 409, 411, 450, 0
146 },
147 /* 640x480 for 80x30 mode */
148 {
149 25175, 640, 664, 760, 800, 480, 491, 493, 525, 0
150 }
151 };
152
153 static void vga_raster_init(struct vga_config *, bus_space_tag_t,
154 bus_space_tag_t);
155 static void vga_raster_init_screen(struct vga_config *, struct vgascreen *,
156 const struct wsscreen_descr *, int, long *);
157 static void vga_raster_setup_font(struct vga_config *, struct vgascreen *);
158 static void vga_setup_regs(struct videomode *, struct vga_moderegs *);
159 static void vga_set_mode(struct vga_handle *, struct vga_moderegs *);
160 static void vga_restore_screen(struct vgascreen *,
161 const struct wsscreen_descr *, struct vga_scrmem *);
162 static void vga_raster_cursor_init(struct vgascreen *, int);
163 static void _vga_raster_putchar(void *, int, int, u_int, long,
164 struct vga_raster_font *);
165
166 static void vga_raster_cursor(void *, int, int, int);
167 static int vga_raster_mapchar(void *, int, u_int *);
168 static void vga_raster_putchar(void *, int, int, u_int, long);
169 static void vga_raster_copycols(void *, int, int, int, int);
170 static void vga_raster_erasecols(void *, int, int, int, long);
171 static void vga_raster_copyrows(void *, int, int, int);
172 static void vga_raster_eraserows(void *, int, int, long);
173 static int vga_raster_allocattr(void *, int, int, int, long *);
174
175 const struct wsdisplay_emulops vga_raster_emulops = {
176 vga_raster_cursor,
177 vga_raster_mapchar,
178 vga_raster_putchar,
179 vga_raster_copycols,
180 vga_raster_erasecols,
181 vga_raster_copyrows,
182 vga_raster_eraserows,
183 vga_raster_allocattr,
184 };
185
186 /*
187 * translate WS(=ANSI) color codes to standard pc ones
188 */
189 static const unsigned char fgansitopc[] = {
190 #ifdef __alpha__
191 /*
192 * XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!!
193 * XXX We should probably not bother with this
194 * XXX (reinitialize the palette registers).
195 */
196 FG_BLACK, FG_BLUE, FG_GREEN, FG_CYAN, FG_RED,
197 FG_MAGENTA, FG_BROWN, FG_LIGHTGREY
198 #else
199 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
200 FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
201 #endif
202 }, bgansitopc[] = {
203 #ifdef __alpha__
204 BG_BLACK, BG_BLUE, BG_GREEN, BG_CYAN, BG_RED,
205 BG_MAGENTA, BG_BROWN, BG_LIGHTGREY
206 #else
207 BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
208 BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
209 #endif
210 };
211
212 const struct wsscreen_descr vga_25lscreen = {
213 "80x25", 80, 25,
214 &vga_raster_emulops,
215 8, 16,
216 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
217 &vga_console_modes[0]
218 }, vga_25lscreen_mono = {
219 "80x25", 80, 25,
220 &vga_raster_emulops,
221 8, 16,
222 WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
223 &vga_console_modes[0]
224 }, vga_30lscreen = {
225 "80x30", 80, 30,
226 &vga_raster_emulops,
227 8, 16,
228 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
229 &vga_console_modes[1]
230 }, vga_30lscreen_mono = {
231 "80x30", 80, 30,
232 &vga_raster_emulops,
233 8, 16,
234 WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
235 &vga_console_modes[1]
236 }, vga_40lscreen = {
237 "80x40", 80, 40,
238 &vga_raster_emulops,
239 8, 10,
240 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
241 &vga_console_modes[0]
242 }, vga_40lscreen_mono = {
243 "80x40", 80, 40,
244 &vga_raster_emulops,
245 8, 10,
246 WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
247 &vga_console_modes[0]
248 }, vga_50lscreen = {
249 "80x50", 80, 50,
250 &vga_raster_emulops,
251 8, 8,
252 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
253 &vga_console_modes[0]
254 }, vga_50lscreen_mono = {
255 "80x50", 80, 50,
256 &vga_raster_emulops,
257 8, 8,
258 WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
259 &vga_console_modes[0]
260 };
261
262 const struct wsscreen_descr *_vga_scrlist[] = {
263 &vga_25lscreen,
264 &vga_30lscreen,
265 &vga_40lscreen,
266 &vga_50lscreen,
267 }, *_vga_scrlist_mono[] = {
268 &vga_25lscreen_mono,
269 &vga_30lscreen_mono,
270 &vga_40lscreen_mono,
271 &vga_50lscreen_mono,
272 };
273
274 const struct wsscreen_list vga_screenlist = {
275 sizeof(_vga_scrlist) / sizeof(struct wsscreen_descr *),
276 _vga_scrlist
277 }, vga_screenlist_mono = {
278 sizeof(_vga_scrlist_mono) / sizeof(struct wsscreen_descr *),
279 _vga_scrlist_mono
280 };
281
282 static int vga_raster_ioctl(void *, u_long, caddr_t, int, struct proc *);
283 static paddr_t vga_raster_mmap(void *, off_t, int);
284 static int vga_raster_alloc_screen(void *, const struct wsscreen_descr *,
285 void **, int *, int *, long *);
286 static void vga_raster_free_screen(void *, void *);
287 static int vga_raster_show_screen(void *, void *, int,
288 void (*)(void *, int, int), void *);
289 static int vga_raster_load_font(void *, void *, struct wsdisplay_font *);
290
291 static void vga_switch_screen(struct vga_config *);
292 static void vga_raster_setscreentype(struct vga_config *,
293 const struct wsscreen_descr *);
294
295 const struct wsdisplay_accessops vga_raster_accessops = {
296 vga_raster_ioctl,
297 vga_raster_mmap,
298 vga_raster_alloc_screen,
299 vga_raster_free_screen,
300 vga_raster_show_screen,
301 vga_raster_load_font,
302 };
303
304 int
305 vga_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check)
306 {
307 long defattr;
308 const struct wsscreen_descr *scr;
309
310 if (check && !vga_common_probe(iot, memt))
311 return (ENXIO);
312
313 /* set up bus-independent VGA configuration */
314 vga_raster_init(&vga_console_vc, iot, memt);
315 #ifdef VGA_CONSOLE_SCREENTYPE
316 scr = wsdisplay_screentype_pick(vga_console_vc.hdl.vh_mono ?
317 &vga_screenlist_mono : &vga_screenlist, VGA_CONSOLE_SCREENTYPE);
318 if (!scr)
319 panic("vga_cnattach: invalid screen type");
320 if (scr != vga_console_vc.currenttype) {
321 vga_raster_setscreentype(&vga_console_vc, scr);
322 vga_console_vc.currenttype = scr;
323 }
324 #else
325 scr = vga_console_vc.currenttype;
326 #endif
327 vga_raster_init_screen(&vga_console_vc, &vga_console_screen, scr, 1,
328 &defattr);
329
330 vga_console_screen.active = 1;
331 vga_console_vc.active = &vga_console_screen;
332
333 wsdisplay_cnattach(scr, &vga_console_screen,
334 vga_console_screen.cursorcol, vga_console_screen.cursorrow,
335 defattr);
336
337 vgaconsole = 1;
338 vga_console_type = type;
339 return (0);
340 }
341
342 void
343 vga_raster_init(struct vga_config *vc, bus_space_tag_t iot,
344 bus_space_tag_t memt)
345 {
346 struct vga_handle *vh = &vc->hdl;
347 u_int8_t mor;
348 struct vga_raster_font *vf;
349 int i;
350
351 vh->vh_iot = iot;
352 vh->vh_memt = memt;
353
354 if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga))
355 panic("vga_raster_init: couldn't map vga io");
356
357 /* read "misc output register" */
358 mor = bus_space_read_1(vh->vh_iot, vh->vh_ioh_vga, 0xc);
359 vh->vh_mono = !(mor & 1);
360
361 if (bus_space_map(vh->vh_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0,
362 &vh->vh_ioh_6845))
363 panic("vga_raster_init: couldn't map 6845 io");
364
365 if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh))
366 panic("vga_raster_init: couldn't map memory");
367
368 if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh, 0, 0x10000,
369 &vh->vh_memh))
370 panic("vga_raster_init: mem subrange failed");
371
372 /* should only reserve the space (no need to map - save KVM) */
373 vc->vc_biostag = memt;
374 if (bus_space_map(vc->vc_biostag, 0xc0000, 0x8000, 0, &vc->vc_bioshdl))
375 vc->vc_biosmapped = 0;
376 else
377 vc->vc_biosmapped = 1;
378
379 vc->nscreens = 0;
380 LIST_INIT(&vc->screens);
381 vc->active = NULL;
382 vc->currenttype = vh->vh_mono ? &vga_25lscreen_mono : &vga_25lscreen;
383 callout_init(&vc->vc_switch_callout);
384
385 /* Save the current screen to memory. XXXBJY assume 80x25 */
386 for (i = 0; i < 80 * 25; i++) {
387 boot_scrmem[i].ch = bus_space_read_1(vh->vh_memt,
388 vh->vh_allmemh, 0x18000 + i * 2);
389 boot_scrmem[i].attr = bus_space_read_1(vh->vh_memt,
390 vh->vh_allmemh, 0x18000 + i * 2 + 1);
391 boot_scrmem[i].enc = WSDISPLAY_FONTENC_IBM;
392 }
393
394 vc->nfonts = 1;
395 LIST_INIT(&vc->vc_fontlist);
396 vf = &vga_console_fontset_ascii;
397 vga_load_builtinfont(vh, builtinfont_data, 0, 256);
398 vf->font = &builtinfont;
399 LIST_INSERT_HEAD(&vc->vc_fontlist, vf, next);
400 }
401
402 void
403 vga_raster_init_screen(struct vga_config *vc, struct vgascreen *scr,
404 const struct wsscreen_descr *type, int existing, long *attrp)
405 {
406 int cpos;
407 int res;
408 struct vga_handle *vh;
409 struct vga_moderegs moderegs;
410
411 scr->cfg = vc;
412 scr->hdl = &vc->hdl;
413 scr->type = type;
414 scr->mindispoffset = 0;
415 scr->maxdispoffset = 0x10000;
416 scr->encoding = WSDISPLAY_FONTENC_IBM;
417 vh = &vc->hdl;
418
419 wsfont_init();
420 LIST_INIT(&scr->fontset);
421 vga_raster_setup_font(vc, scr);
422
423 if (existing) {
424 cpos = vga_6845_read(vh, cursorh) << 8;
425 cpos |= vga_6845_read(vh, cursorl);
426
427 /* make sure we have a valid cursor position */
428 if (cpos < 0 || cpos >= type->nrows * type->ncols)
429 cpos = 0;
430
431 scr->dispoffset = vga_6845_read(vh, startadrh) << 9;
432 scr->dispoffset |= vga_6845_read(vh, startadrl) << 1;
433
434 /* make sure we have a valid memory offset */
435 if (scr->dispoffset < scr->mindispoffset ||
436 scr->dispoffset > scr->maxdispoffset)
437 scr->dispoffset = scr->mindispoffset;
438
439 scr->mem = boot_scrmem;
440 scr->active = 1;
441
442 vga_raster_setscreentype(vc, type);
443
444 /* Clear the entire screen. */
445 vga_gdc_write(vh, mode, 0x02);
446 bus_space_set_region_4(vh->vh_memt, vh->vh_allmemh, 0, 0,
447 0x4000);
448
449 vga_restore_screen(scr, type, scr->mem);
450
451 /* Delay to prevent the boot screen from being too
452 fast scrolled up. */
453 delay(1000000);
454 } else {
455 cpos = 0;
456 scr->dispoffset = scr->mindispoffset;
457 scr->mem = NULL;
458 scr->active = 0;
459 }
460
461 scr->cursorrow = cpos / type->ncols;
462 scr->cursorcol = cpos % type->ncols;
463 vga_raster_cursor_init(scr, existing);
464
465 #ifdef __alpha__
466 if (!vc->hdl.vh_mono)
467 /*
468 * DEC firmware uses a blue background.
469 */
470 res = vga_raster_allocattr(scr, WSCOL_WHITE, WSCOL_BLUE,
471 WSATTR_WSCOLORS, attrp);
472 else
473 #endif
474 res = vga_raster_allocattr(scr, 0, 0, 0, attrp);
475 #ifdef DIAGNOSTIC
476 if (res)
477 panic("vga_raster_init_screen: attribute botch");
478 #endif
479
480 vc->nscreens++;
481 LIST_INSERT_HEAD(&vc->screens, scr, next);
482 }
483
484 void
485 vga_common_attach(struct vga_softc *sc, bus_space_tag_t iot,
486 bus_space_tag_t memt, int type, int quirks, const struct vga_funcs *vf)
487 {
488 int console;
489 struct vga_config *vc;
490 struct wsemuldisplaydev_attach_args aa;
491
492 console = vga_is_console(iot, type);
493
494 if (console) {
495 vc = &vga_console_vc;
496 vga_console_attached = 1;
497 } else {
498 vc = malloc(sizeof(struct vga_config), M_DEVBUF,
499 M_WAITOK);
500 vga_raster_init(vc, iot, memt);
501 }
502
503 vc->vc_type = type;
504 vc->vc_funcs = vf;
505
506 sc->sc_vc = vc;
507 vc->softc = sc;
508
509 aa.console = console;
510 aa.scrdata = (vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist);
511 aa.accessops = &vga_raster_accessops;
512 aa.accesscookie = vc;
513
514 config_found(&sc->sc_dev, &aa, wsemuldisplaydevprint);
515 }
516
517 int
518 vga_is_console(bus_space_tag_t iot, int type)
519 {
520 if (vgaconsole &&
521 !vga_console_attached &&
522 iot == vga_console_vc.hdl.vh_iot &&
523 (vga_console_type == -1 || (type == vga_console_type)))
524 return (1);
525 return (0);
526 }
527
528 #define VGA_TS_BLANK 0x20
529
530 static int
531 vga_get_video(struct vga_config *vc)
532 {
533 return (vga_ts_read(&vc->hdl, mode) & VGA_TS_BLANK) == 0;
534 }
535
536 static void
537 vga_set_video(struct vga_config *vc, int state)
538 {
539 int val;
540
541 vga_ts_write(&vc->hdl, syncreset, 0x01);
542 if (state) { /* unblank screen */
543 val = vga_ts_read(&vc->hdl, mode);
544 vga_ts_write(&vc->hdl, mode, val & ~VGA_TS_BLANK);
545 #ifndef VGA_NO_VBLANK
546 val = vga_6845_read(&vc->hdl, mode);
547 vga_6845_write(&vc->hdl, mode, val | 0x80);
548 #endif
549 } else { /* blank screen */
550 val = vga_ts_read(&vc->hdl, mode);
551 vga_ts_write(&vc->hdl, mode, val | VGA_TS_BLANK);
552 #ifndef VGA_NO_VBLANK
553 val = vga_6845_read(&vc->hdl, mode);
554 vga_6845_write(&vc->hdl, mode, val & ~0x80);
555 #endif
556 }
557 vga_ts_write(&vc->hdl, syncreset, 0x03);
558 }
559
560 int
561 vga_raster_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
562 {
563 struct vga_config *vc = v;
564 const struct vga_funcs *vf = vc->vc_funcs;
565
566 switch (cmd) {
567 case WSDISPLAYIO_GTYPE:
568 *(int *)data = vc->vc_type;
569 return 0;
570
571 case WSDISPLAYIO_GINFO:
572 /* XXX should get detailed hardware information here */
573 return EPASSTHROUGH;
574
575 case WSDISPLAYIO_GVIDEO:
576 #if 1
577 *(int *)data = (vga_get_video(vc) ? WSDISPLAYIO_VIDEO_ON :
578 WSDISPLAYIO_VIDEO_OFF);
579 return 0;
580 #endif
581
582 case WSDISPLAYIO_SVIDEO:
583 #if 1
584 vga_set_video(vc, *(int *)data == WSDISPLAYIO_VIDEO_ON);
585 return 0;
586 #endif
587
588 case WSDISPLAYIO_GETCMAP:
589 case WSDISPLAYIO_PUTCMAP:
590 case WSDISPLAYIO_GCURPOS:
591 case WSDISPLAYIO_SCURPOS:
592 case WSDISPLAYIO_GCURMAX:
593 case WSDISPLAYIO_GCURSOR:
594 case WSDISPLAYIO_SCURSOR:
595 /* NONE of these operations are by the generic VGA driver. */
596 return EPASSTHROUGH;
597 }
598
599 if (vc->vc_funcs == NULL)
600 return (EPASSTHROUGH);
601
602 if (vf->vf_ioctl == NULL)
603 return (EPASSTHROUGH);
604
605 return ((*vf->vf_ioctl)(v, cmd, data, flag, p));
606
607 }
608
609 static paddr_t
610 vga_raster_mmap(void *v, off_t offset, int prot)
611 {
612 struct vga_config *vc = v;
613 const struct vga_funcs *vf = vc->vc_funcs;
614
615 if (vc->vc_funcs == NULL)
616 return (-1);
617
618 if (vf->vf_mmap == NULL)
619 return (-1);
620
621 return ((*vf->vf_mmap)(v, offset, prot));
622 }
623
624 int
625 vga_raster_alloc_screen(void *v, const struct wsscreen_descr *type,
626 void **cookiep, int *curxp, int *curyp, long *defattrp)
627 {
628 struct vga_config *vc = v;
629 struct vgascreen *scr;
630
631 if (vc->nscreens == 1) {
632 vc->screens.lh_first->mem = boot_scrmem;
633 }
634
635 scr = malloc(sizeof(struct vgascreen), M_DEVBUF, M_WAITOK);
636 vga_raster_init_screen(vc, scr, type, vc->nscreens == 0, defattrp);
637
638 if (vc->nscreens == 1) {
639 scr->active = 1;
640 vc->active = scr;
641 vc->currenttype = type;
642 } else {
643 scr->mem = malloc(sizeof(struct vga_scrmem) *
644 type->ncols * type->nrows, M_DEVBUF, M_WAITOK);
645 vga_raster_eraserows(scr, 0, type->nrows, *defattrp);
646 }
647
648 *cookiep = scr;
649 *curxp = scr->cursorcol;
650 *curyp = scr->cursorrow;
651
652 return (0);
653 }
654
655 void
656 vga_raster_free_screen(void *v, void *cookie)
657 {
658 struct vgascreen *vs = cookie;
659 struct vga_config *vc = vs->cfg;
660
661 LIST_REMOVE(vs, next);
662 if (vs != &vga_console_screen)
663 free(vs, M_DEVBUF);
664 else
665 panic("vga_raster_free_screen: console");
666
667 if (vc->active == vs)
668 vc->active = 0;
669 }
670
671 int
672 vga_raster_show_screen(void *v, void *cookie, int waitok,
673 void (*cb)(void *, int, int), void *cbarg)
674 {
675 struct vgascreen *scr = cookie, *oldscr;
676 struct vga_config *vc = scr->cfg;
677
678 oldscr = vc->active; /* can be NULL! */
679 if (scr == oldscr) {
680 return (0);
681 }
682
683 vc->wantedscreen = cookie;
684 vc->switchcb = cb;
685 vc->switchcbarg = cbarg;
686 if (cb) {
687 callout_reset(&vc->vc_switch_callout, 0,
688 (void(*)(void *))vga_switch_screen, vc);
689 return (EAGAIN);
690 }
691
692 vga_switch_screen(vc);
693 return (0);
694 }
695
696 void
697 vga_switch_screen(struct vga_config *vc)
698 {
699 struct vgascreen *scr, *oldscr;
700 struct vga_handle *vh = &vc->hdl;
701 const struct wsscreen_descr *type;
702
703 scr = vc->wantedscreen;
704 if (!scr) {
705 printf("vga_switch_screen: disappeared\n");
706 (*vc->switchcb)(vc->switchcbarg, EIO, 0);
707 return;
708 }
709 type = scr->type;
710 oldscr = vc->active; /* can be NULL! */
711 #ifdef DIAGNOSTIC
712 if (oldscr) {
713 if (!oldscr->active)
714 panic("vga_raster_show_screen: not active");
715 if (oldscr->type != vc->currenttype)
716 panic("vga_raster_show_screen: bad type");
717 }
718 #endif
719 if (scr == oldscr) {
720 return;
721 }
722 #ifdef DIAGNOSTIC
723 if (scr->active)
724 panic("vga_raster_show_screen: active");
725 #endif
726
727 if (oldscr)
728 oldscr->active = 0;
729
730 if (vc->currenttype != type) {
731 vga_raster_setscreentype(vc, type);
732 vc->currenttype = type;
733 }
734
735 scr->dispoffset = scr->mindispoffset;
736
737 if (!oldscr || (scr->dispoffset != oldscr->dispoffset)) {
738 vga_6845_write(vh, startadrh, scr->dispoffset >> 8);
739 vga_6845_write(vh, startadrl, scr->dispoffset);
740 }
741
742 /* Clear the entire screen. */
743 vga_gdc_write(vh, mode, 0x02);
744 bus_space_set_region_4(vh->vh_memt, vh->vh_allmemh, 0, 0, 0x2000);
745
746 scr->active = 1;
747 vga_restore_screen(scr, type, scr->mem);
748
749 vc->active = scr;
750
751 vga_raster_cursor(scr, scr->cursoron, scr->cursorrow, scr->cursorcol);
752
753 vc->wantedscreen = 0;
754 if (vc->switchcb)
755 (*vc->switchcb)(vc->switchcbarg, 0, 0);
756 }
757
758 static int
759 vga_raster_load_font(void *v, void *id, struct wsdisplay_font *data)
760 {
761 /* XXX */
762
763 return (0);
764 }
765
766 void
767 vga_raster_setup_font(struct vga_config *vc, struct vgascreen *scr)
768 {
769 struct vga_raster_font *vf;
770 struct wsdisplay_font *wf;
771 int cookie;
772
773 LIST_FOREACH(vf, &vc->vc_fontlist, next) {
774 if (wsfont_matches(vf->font, 0, 0, scr->type->fontheight, 0)) {
775 LIST_INSERT_HEAD(&scr->fontset, vf, next);
776 return;
777 }
778 }
779
780 cookie = wsfont_find(0, 0, scr->type->fontheight, 0,
781 WSDISPLAY_FONTORDER_L2R, 0);
782 if (cookie == -1)
783 return;
784
785 if (wsfont_lock(cookie, &wf))
786 return;
787
788 vf = malloc(sizeof(struct vga_raster_font), M_DEVBUF, M_NOWAIT);
789 if (!vf) {
790 wsfont_unlock(cookie);
791 return;
792 }
793
794 vf->font = wf;
795 LIST_INSERT_HEAD(&scr->fontset, vf, next);
796 }
797
798 void
799 vga_setup_regs(struct videomode *mode, struct vga_moderegs *regs)
800 {
801 int i;
802 int depth = 4; /* XXXBJY hardcoded for now */
803 int palette[16] = {
804 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
805 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
806 };
807
808 /*
809 * Compute hsync and vsync polarity.
810 */
811 if ((mode->flags & (VID_PHSYNC | VID_NHSYNC))
812 && (mode->flags & (VID_PVSYNC | VID_NVSYNC))) {
813 regs->miscout = 0x23;
814 if (mode->flags & VID_NHSYNC)
815 regs->miscout |= 0x40;
816 if (mode->flags & VID_NVSYNC)
817 regs->miscout |= 0x80;
818 } else {
819 if (mode->flags & VID_DBLSCAN)
820 mode->vdisplay *= 2;
821 if (mode->vdisplay < 400)
822 regs->miscout = 0xa3;
823 if (mode->vdisplay < 480)
824 regs->miscout = 0x63;
825 if (mode->vdisplay < 768)
826 regs->miscout = 0xe3;
827 else
828 regs->miscout = 0x23;
829 }
830
831 /*
832 * Time sequencer
833 */
834 if (depth == 4)
835 regs->ts[0] = 0x02;
836 else
837 regs->ts[0] = 0x00;
838 if (mode->flags & VID_CLKDIV2)
839 regs->ts[1] = 0x09;
840 else
841 regs->ts[1] = 0x01;
842 regs->ts[2] = 0x0f;
843 regs->ts[3] = 0x00;
844 if (depth < 8)
845 regs->ts[4] = 0x06;
846 else
847 regs->ts[4] = 0x0e;
848
849 /*
850 * CRTC controller
851 */
852 regs->crtc[0] = (mode->htotal >> 3) - 5;
853 regs->crtc[1] = (mode->hdisplay >> 3) - 1;
854 regs->crtc[2] = (mode->hsync_start >> 3) - 1;
855 regs->crtc[3] = (((mode->hsync_end >> 3) - 1) & 0x1f) | 0x80;
856 regs->crtc[4] = mode->hsync_start >> 3;
857 regs->crtc[5] = ((((mode->hsync_end >> 3) - 1) & 0x20) << 2)
858 | (((mode->hsync_end >> 3)) & 0x1f);
859 regs->crtc[6] = (mode->vtotal - 2) & 0xff;
860 regs->crtc[7] = (((mode->vtotal - 2) & 0x100) >> 8)
861 | (((mode->vdisplay - 1) & 0x100) >> 7)
862 | ((mode->vsync_start & 0x100) >> 6)
863 | (((mode->vsync_start - 1) & 0x100) >> 5)
864 | 0x10
865 | (((mode->vtotal - 2) & 0x200) >> 4)
866 | (((mode->vdisplay - 1) & 0x200) >> 3)
867 | ((mode->vsync_start & 0x200) >> 2);
868 regs->crtc[8] = 0x00;
869 regs->crtc[9] = (((mode->vsync_start - 1) & 0x200) >> 4) | 0x40;
870 if (mode->flags & VID_DBLSCAN)
871 regs->crtc[9] |= 0x80;
872 regs->crtc[10] = 0x00;
873 regs->crtc[11] = 0x00;
874 regs->crtc[12] = 0x00;
875 regs->crtc[13] = 0x00;
876 regs->crtc[14] = 0x00;
877 regs->crtc[15] = 0x00;
878 regs->crtc[16] = mode->vsync_start & 0xff;
879 regs->crtc[17] = (mode->vsync_end & 0x0f) | 0x20;
880 regs->crtc[18] = (mode->vdisplay - 1) & 0xff;
881 regs->crtc[19] = mode->hdisplay >> 4; /* XXXBJY */
882 regs->crtc[20] = 0x00;
883 regs->crtc[21] = (mode->vsync_start - 1) & 0xff;
884 regs->crtc[22] = (mode->vsync_end - 1) & 0xff;
885 if (depth < 8)
886 regs->crtc[23] = 0xe3;
887 else
888 regs->crtc[23] = 0xc3;
889 regs->crtc[24] = 0xff;
890
891 /*
892 * Graphics display controller
893 */
894 regs->gdc[0] = 0x00;
895 regs->gdc[1] = 0x00;
896 regs->gdc[2] = 0x00;
897 regs->gdc[3] = 0x00;
898 regs->gdc[4] = 0x00;
899 if (depth == 4)
900 regs->gdc[5] = 0x02;
901 else
902 regs->gdc[5] = 0x40;
903 regs->gdc[6] = 0x01;
904 regs->gdc[7] = 0x0f;
905 regs->gdc[8] = 0xff;
906
907 /*
908 * Attribute controller
909 */
910 /* Set palette registers. */
911 for (i = 0; i < 16; i++)
912 regs->atc[i] = palette[i];
913 if (depth == 4)
914 regs->atc[16] = 0x01; /* XXXBJY was 0x81 in XFree86 */
915 else
916 regs->atc[16] = 0x41;
917 regs->atc[17] = 0x00; /* XXXBJY just a guess */
918 regs->atc[18] = 0x0f;
919 regs->atc[19] = 0x00;
920 regs->atc[20] = 0x00;
921 }
922
923 void
924 vga_set_mode(struct vga_handle *vh, struct vga_moderegs *regs)
925 {
926 int i;
927
928 /* Disable display. */
929 vga_ts_write(vh, mode, vga_ts_read(vh, mode) | 0x20);
930
931 /* Write misc output register. */
932 bus_space_write_1(vh->vh_iot, vh->vh_ioh_vga, VGA_MISC_DATAW,
933 regs->miscout);
934
935 /* Set synchronous reset. */
936 vga_ts_write(vh, syncreset, 0x01);
937 vga_ts_write(vh, mode, regs->ts[1] | 0x20);
938 for (i = 2; i < VGA_TS_NREGS; i++)
939 _vga_ts_write(vh, i, regs->ts[i]);
940 /* Clear synchronous reset. */
941 vga_ts_write(vh, syncreset, 0x03);
942
943 /* Unprotect CRTC registers 0-7. */
944 _vga_crtc_write(vh, 17, _vga_crtc_read(vh, 17) & 0x7f);
945 /* Write CRTC registers. */
946 for (i = 0; i < VGA_CRTC_NREGS; i++)
947 _vga_crtc_write(vh, i, regs->crtc[i]);
948
949 /* Write graphics display registers. */
950 for (i = 0; i < VGA_GDC_NREGS; i++)
951 _vga_gdc_write(vh, i, regs->gdc[i]);
952
953 /* Write attribute controller registers. */
954 for (i = 0; i < VGA_ATC_NREGS; i++)
955 _vga_attr_write(vh, i, regs->atc[i]);
956
957 /* Enable display. */
958 vga_ts_write(vh, mode, vga_ts_read(vh, mode) & 0xdf);
959 }
960
961 void
962 vga_raster_cursor_init(struct vgascreen *scr, int existing)
963 {
964 struct vga_handle *vh = scr->hdl;
965 bus_space_tag_t memt;
966 bus_space_handle_t memh;
967 int off;
968
969 if (existing) {
970 /*
971 * This is the first screen. At this point, scr->active is
972 * false, so we can't use vga_raster_cursor() to do this.
973 */
974 memt = vh->vh_memt;
975 memh = vh->vh_memh;
976 off = (scr->cursorrow * scr->type->ncols + scr->cursorcol) +
977 scr->dispoffset / 8;
978
979 scr->cursortmp = scr->mem[off];
980 vga_raster_putchar(scr, scr->cursorrow, scr->cursorcol,
981 scr->cursortmp.ch, scr->cursortmp.attr ^ 0x77);
982 } else {
983 scr->cursortmp.ch = 0;
984 scr->cursortmp.attr = 0;
985 scr->cursortmp.second = 0;
986 scr->cursortmp.enc = WSDISPLAY_FONTENC_IBM;
987 }
988
989 scr->cursoron = 1;
990 }
991
992 void
993 vga_raster_cursor(void *id, int on, int row, int col)
994 {
995 struct vgascreen *scr = id;
996 int off, tmp;
997
998 /* Remove old cursor image */
999 if (scr->cursoron) {
1000 off = scr->cursorrow * scr->type->ncols + scr->cursorcol;
1001 if (scr->active) {
1002 tmp = scr->encoding;
1003 scr->encoding = scr->cursortmp.enc;
1004 if (scr->cursortmp.second)
1005 vga_raster_putchar(id, scr->cursorrow,
1006 scr->cursorcol - 1, scr->cursortmp.ch,
1007 scr->cursortmp.attr);
1008 else
1009 vga_raster_putchar(id, scr->cursorrow,
1010 scr->cursorcol, scr->cursortmp.ch,
1011 scr->cursortmp.attr);
1012 scr->encoding = tmp;
1013 }
1014 }
1015
1016 scr->cursorrow = row;
1017 scr->cursorcol = col;
1018
1019 if ((scr->cursoron = on) == 0)
1020 return;
1021
1022 off = scr->cursorrow * scr->type->ncols + scr->cursorcol;
1023 scr->cursortmp = scr->mem[off];
1024 if (scr->active) {
1025 tmp = scr->encoding;
1026 scr->encoding = scr->cursortmp.enc;
1027 if (scr->cursortmp.second)
1028 vga_raster_putchar(id, scr->cursorrow,
1029 scr->cursorcol - 1, scr->cursortmp.ch,
1030 scr->cursortmp.attr ^ 0x77);
1031 else
1032 vga_raster_putchar(id, scr->cursorrow,
1033 scr->cursorcol, scr->cursortmp.ch,
1034 scr->cursortmp.attr ^ 0x77);
1035 scr->encoding = tmp;
1036 }
1037 }
1038
1039 static int
1040 vga_raster_mapchar(void *id, int uni, u_int *index)
1041 {
1042 struct vgascreen *scr = id;
1043
1044 if (scr->encoding == WSDISPLAY_FONTENC_IBM)
1045 return pcdisplay_mapchar(id, uni, index);
1046 else {
1047 *index = uni;
1048 return 5;
1049 }
1050 }
1051
1052 void
1053 vga_raster_putchar(void *id, int row, int col, u_int c, long attr)
1054 {
1055 struct vgascreen *scr = id;
1056 int off;
1057 struct vga_raster_font *fs;
1058 u_int tmp_ch;
1059
1060 off = row * scr->type->ncols + col;
1061
1062 LIST_FOREACH(fs, &scr->fontset, next) {
1063 if ((scr->encoding == fs->font->encoding) &&
1064 (c >= fs->font->firstchar) &&
1065 (c < fs->font->firstchar + fs->font->numchars) &&
1066 (scr->type->fontheight == fs->font->fontheight)) {
1067 if (scr->active) {
1068 tmp_ch = c - fs->font->firstchar;
1069 _vga_raster_putchar(scr, row, col, tmp_ch,
1070 attr, fs);
1071 }
1072
1073 scr->mem[off].ch = c;
1074 scr->mem[off].attr = attr;
1075 scr->mem[off].second = 0;
1076 scr->mem[off].enc = fs->font->encoding;
1077
1078 if (fs->font->stride == 2) {
1079 scr->mem[off + 1].ch = c;
1080 scr->mem[off + 1].attr = attr;
1081 scr->mem[off + 1].second = 1;
1082 scr->mem[off + 1].enc = fs->font->encoding;
1083 }
1084
1085 return;
1086 }
1087 }
1088
1089 /*
1090 * No match found.
1091 */
1092 if (scr->active)
1093 /* Put a single width space character no matter what the
1094 actual width of the character is. */
1095 _vga_raster_putchar(scr, row, col, 0x20, attr,
1096 &vga_console_fontset_ascii);
1097 scr->mem[off].ch = c;
1098 scr->mem[off].attr = attr;
1099 scr->mem[off].second = 0;
1100 scr->mem[off].enc = WSDISPLAY_FONTENC_IBM;
1101 }
1102
1103 static void
1104 _vga_raster_putchar(void *id, int row, int col, u_int c, long attr,
1105 struct vga_raster_font *fs)
1106 {
1107 struct vgascreen *scr = id;
1108 struct vga_handle *vh = scr->hdl;
1109 bus_space_tag_t memt = vh->vh_memt;
1110 bus_space_handle_t memh = vh->vh_memh;
1111 int i;
1112 int rasoff, rasoff2;
1113 int fheight = scr->type->fontheight;
1114 volatile u_int8_t dummy, pattern;
1115 u_int8_t fgcolor, bgcolor;
1116
1117 rasoff = scr->dispoffset + row * scr->type->ncols * fheight + col;
1118 rasoff2 = rasoff;
1119
1120 #if 0
1121 bgcolor = bgansitopc[attr >> 4];
1122 fgcolor = fgansitopc[attr & 0x0f];
1123 #else
1124 bgcolor = ((attr >> 4) & 0x0f);
1125 fgcolor = attr & 0x0f;
1126 #endif
1127
1128 if (fs->font->stride == 1) {
1129 /* Paint background. */
1130 vga_gdc_write(vh, mode, 0x02);
1131 for (i = 0; i < fheight; i++) {
1132 bus_space_write_1(memt, memh, rasoff, bgcolor);
1133 rasoff += scr->type->ncols;
1134 }
1135
1136 /* Draw a single width character. */
1137 vga_gdc_write(vh, mode, 0x03);
1138 vga_gdc_write(vh, setres, fgcolor);
1139 for (i = 0; i < fheight; i++) {
1140 pattern = ((u_int8_t *)fs->font->data)[c * fheight + i];
1141 /* When pattern is 0, skip output for speed-up. */
1142 if (pattern != 0) {
1143 dummy = bus_space_read_1(memt, memh, rasoff2);
1144 bus_space_write_1(memt, memh, rasoff2, pattern);
1145 }
1146 rasoff2 += scr->type->ncols;
1147 }
1148 } else if (fs->font->stride == 2) {
1149 /* Paint background. */
1150 vga_gdc_write(vh, mode, 0x02);
1151 for (i = 0; i < fheight; i++) {
1152 bus_space_write_1(memt, memh, rasoff, bgcolor);
1153 bus_space_write_1(memt, memh, rasoff + 1, bgcolor);
1154 rasoff += scr->type->ncols;
1155 }
1156
1157 /* Draw a double width character. */
1158 vga_gdc_write(vh, mode, 0x03);
1159 vga_gdc_write(vh, setres, fgcolor);
1160 for (i = 0; i < fheight; i++) {
1161 pattern = ((u_int8_t *)fs->font->data)
1162 [(c * fheight + i) * 2];
1163 if (pattern != 0) {
1164 dummy = bus_space_read_1(memt, memh, rasoff2);
1165 bus_space_write_1(memt, memh, rasoff2, pattern);
1166 }
1167 pattern = ((u_int8_t *)fs->font->data)
1168 [(c * fheight + i) * 2 + 1];
1169 if (pattern != 0) {
1170 rasoff2++;
1171 dummy = bus_space_read_1(memt, memh, rasoff2);
1172 bus_space_write_1(memt, memh, rasoff2, pattern);
1173 rasoff2--;
1174 }
1175 rasoff2 += scr->type->ncols;
1176 }
1177 }
1178 }
1179
1180 void
1181 vga_raster_copycols(void *id, int row, int srccol, int dstcol, int ncols)
1182 {
1183 struct vgascreen *scr = id;
1184 struct vga_handle *vh = scr->hdl;
1185 bus_space_tag_t memt = vh->vh_memt;
1186 bus_space_handle_t memh = vh->vh_memh;
1187 bus_size_t srcoff, dstoff;
1188 bus_size_t rassrcoff, rasdstoff;
1189 int i;
1190 int fheight = scr->type->fontheight;
1191
1192 srcoff = row * scr->type->ncols + srccol;
1193 dstoff = row * scr->type->ncols + dstcol;
1194 rassrcoff = scr->dispoffset + row * scr->type->ncols * fheight + srccol;
1195 rasdstoff = scr->dispoffset + row * scr->type->ncols * fheight + dstcol;
1196
1197 memcpy(&scr->mem[dstoff], &scr->mem[srcoff],
1198 ncols * sizeof(struct vga_scrmem));
1199
1200 vga_gdc_write(vh, mode, 0x01);
1201 if (scr->active) {
1202 for (i = 0; i < fheight; i++) {
1203 bus_space_copy_region_1(memt, memh,
1204 rassrcoff + i * scr->type->ncols, memh,
1205 rasdstoff + i * scr->type->ncols, ncols);
1206 }
1207 }
1208 }
1209
1210 void
1211 vga_raster_erasecols(void *id, int row, int startcol, int ncols, long fillattr)
1212 {
1213 struct vgascreen *scr = id;
1214 int i;
1215
1216 if (scr->active == 0)
1217 return;
1218
1219 for (i = startcol; i < startcol + ncols; i++)
1220 vga_raster_putchar(id, row, i, ' ', fillattr);
1221 }
1222
1223 void
1224 vga_raster_copyrows(void *id, int srcrow, int dstrow, int nrows)
1225 {
1226 struct vgascreen *scr = id;
1227 struct vga_handle *vh = scr->hdl;
1228 bus_space_tag_t memt = vh->vh_memt;
1229 bus_space_handle_t memh = vh->vh_memh;
1230 int ncols;
1231 bus_size_t srcoff, dstoff;
1232 bus_size_t rassrcoff, rasdstoff;
1233 int fheight;
1234
1235 ncols = scr->type->ncols;
1236 fheight = scr->type->fontheight;
1237
1238 srcoff = srcrow * ncols;
1239 dstoff = dstrow * ncols;
1240 rassrcoff = srcoff * fheight;
1241 rasdstoff = dstoff * fheight;
1242
1243 if (scr->active) {
1244 vga_gdc_write(vh, mode, 0x01);
1245 if (dstrow == 0 && (srcrow + nrows == scr->type->nrows)) {
1246 int cursoron = scr->cursoron;
1247
1248 if (cursoron)
1249 /* Disable cursor. */
1250 vga_raster_cursor(scr, 0,
1251 scr->cursorrow, scr->cursorcol);
1252
1253 /* scroll up whole screen */
1254 if ((scr->dispoffset + srcrow * ncols * fheight)
1255 <= scr->maxdispoffset)
1256 scr->dispoffset += srcrow * ncols * fheight;
1257 else {
1258 bus_space_copy_region_1(memt, memh,
1259 scr->dispoffset + rassrcoff,
1260 memh, scr->mindispoffset,
1261 nrows * ncols * fheight);
1262 scr->dispoffset = scr->mindispoffset;
1263 }
1264 vga_6845_write(vh, startadrh, scr->dispoffset >> 8);
1265 vga_6845_write(vh, startadrl, scr->dispoffset);
1266
1267 if (cursoron)
1268 /* Enable cursor. */
1269 vga_raster_cursor(scr, 1, scr->cursorrow,
1270 scr->cursorcol);
1271 } else
1272 bus_space_copy_region_1(memt, memh,
1273 scr->dispoffset + rassrcoff, memh,
1274 scr->dispoffset + rasdstoff,
1275 nrows * ncols * fheight);
1276 }
1277 memcpy(&scr->mem[dstoff], &scr->mem[srcoff],
1278 nrows * ncols * sizeof(struct vga_scrmem));
1279 }
1280
1281 void
1282 vga_raster_eraserows(void *id, int startrow, int nrows, long fillattr)
1283 {
1284 struct vgascreen *scr = id;
1285 struct vga_handle *vh = scr->hdl;
1286 bus_space_tag_t memt = vh->vh_memt;
1287 bus_space_handle_t memh = vh->vh_memh;
1288 bus_size_t off, count;
1289 bus_size_t rasoff, rascount;
1290 int i;
1291
1292 off = startrow * scr->type->ncols;
1293 count = nrows * scr->type->ncols;
1294 rasoff = off * scr->type->fontheight;
1295 rascount = count * scr->type->fontheight;
1296
1297 if (scr->active) {
1298 /* Paint background. */
1299 vga_gdc_write(vh, mode, 0x02);
1300 if (scr->type->ncols % 4 == 0)
1301 /* We can speed up I/O */
1302 for (i = rasoff; i < rasoff + rascount; i += 4)
1303 bus_space_write_4(memt, memh,
1304 scr->dispoffset + i, fillattr >> 4);
1305 else
1306 for (i = rasoff; i < rasoff + rascount; i += 2)
1307 bus_space_write_2(memt, memh,
1308 scr->dispoffset + i, fillattr >> 4);
1309 }
1310 for (i = 0; i < count; i++) {
1311 scr->mem[off + i].ch = ' ';
1312 scr->mem[off + i].attr = fillattr;
1313 scr->mem[off + i].second = 0;
1314 scr->mem[off + i].enc = WSDISPLAY_FONTENC_IBM;
1315 }
1316 }
1317
1318 static int
1319 vga_raster_allocattr(void *id, int fg, int bg, int flags, long *attrp)
1320 {
1321 struct vgascreen *scr = id;
1322 struct vga_config *vc = scr->cfg;
1323
1324 if (vc->hdl.vh_mono) {
1325 if (flags & WSATTR_WSCOLORS)
1326 return (EINVAL);
1327 if (flags & WSATTR_REVERSE)
1328 *attrp = 0x70;
1329 else
1330 *attrp = 0x07;
1331 if (flags & WSATTR_UNDERLINE)
1332 *attrp |= FG_UNDERLINE;
1333 if (flags & WSATTR_HILIT)
1334 *attrp |= FG_INTENSE;
1335 } else {
1336 if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE))
1337 return (EINVAL);
1338 if (flags & WSATTR_WSCOLORS)
1339 *attrp = fgansitopc[fg] | bgansitopc[bg];
1340 else
1341 *attrp = 7;
1342 if (flags & WSATTR_HILIT)
1343 *attrp += 8;
1344 }
1345 if (flags & WSATTR_BLINK)
1346 *attrp |= FG_BLINK;
1347 return (0);
1348 }
1349
1350 void
1351 vga_restore_screen(struct vgascreen *scr,
1352 const struct wsscreen_descr *type, struct vga_scrmem *mem)
1353 {
1354 int i, j, off, tmp;
1355
1356 tmp = scr->encoding;
1357 for (i = 0; i < type->nrows; i++) {
1358 for (j = 0; j < type->ncols; j++) {
1359 off = i * type->ncols + j;
1360 if (mem[off].second != 1) {
1361 scr->encoding = mem[off].enc;
1362 vga_raster_putchar(scr, i, j, mem[off].ch,
1363 mem[off].attr);
1364 }
1365 }
1366 }
1367 scr->encoding = tmp;
1368 }
1369
1370 void
1371 vga_raster_setscreentype(struct vga_config *vc,
1372 const struct wsscreen_descr *type)
1373 {
1374 struct vga_handle *vh = &vc->hdl;
1375 struct vga_moderegs moderegs;
1376
1377 vga_setup_regs((struct videomode *)type->modecookie, &moderegs);
1378 vga_set_mode(vh, &moderegs);
1379 }
1380