vga_raster.c revision 1.1 1 /* $NetBSD: vga_raster.c,v 1.1 2002/10/15 18:14:42 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 /* Set up registers for graphics mode. */
443 vga_setup_regs(&vga_console_modes[0], &moderegs);
444 /* Switch to graphics mode. */
445 vga_set_mode(vh, &moderegs);
446
447 /* Clear the entire screen. */
448 vga_gdc_write(vh, mode, 0x02);
449 bus_space_set_region_4(vh->vh_memt, vh->vh_allmemh, 0, 0,
450 0x4000);
451
452 vga_restore_screen(scr, type, scr->mem);
453
454 /* Delay to prevent the boot screen from being too
455 fast scrolled up. */
456 delay(1200000);
457 } else {
458 cpos = 0;
459 scr->dispoffset = scr->mindispoffset;
460 scr->mem = NULL;
461 scr->active = 0;
462 }
463
464 scr->cursorrow = cpos / type->ncols;
465 scr->cursorcol = cpos % type->ncols;
466 vga_raster_cursor_init(scr, existing);
467
468 #ifdef __alpha__
469 if (!vc->hdl.vh_mono)
470 /*
471 * DEC firmware uses a blue background.
472 */
473 res = vga_raster_allocattr(scr, WSCOL_WHITE, WSCOL_BLUE,
474 WSATTR_WSCOLORS, attrp);
475 else
476 #endif
477 res = vga_raster_allocattr(scr, 0, 0, 0, attrp);
478 #ifdef DIAGNOSTIC
479 if (res)
480 panic("vga_raster_init_screen: attribute botch");
481 #endif
482
483 vc->nscreens++;
484 LIST_INSERT_HEAD(&vc->screens, scr, next);
485 }
486
487 void
488 vga_common_attach(struct vga_softc *sc, bus_space_tag_t iot,
489 bus_space_tag_t memt, int type, int quirks, const struct vga_funcs *vf)
490 {
491 int console;
492 struct vga_config *vc;
493 struct wsemuldisplaydev_attach_args aa;
494
495 console = vga_is_console(iot, type);
496
497 if (console) {
498 vc = &vga_console_vc;
499 vga_console_attached = 1;
500 } else {
501 vc = malloc(sizeof(struct vga_config), M_DEVBUF,
502 M_WAITOK);
503 vga_raster_init(vc, iot, memt);
504 }
505
506 vc->vc_type = type;
507 vc->vc_funcs = vf;
508
509 sc->sc_vc = vc;
510 vc->softc = sc;
511
512 aa.console = console;
513 aa.scrdata = (vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist);
514 aa.accessops = &vga_raster_accessops;
515 aa.accesscookie = vc;
516
517 config_found(&sc->sc_dev, &aa, wsemuldisplaydevprint);
518 }
519
520 int
521 vga_is_console(bus_space_tag_t iot, int type)
522 {
523 if (vgaconsole &&
524 !vga_console_attached &&
525 iot == vga_console_vc.hdl.vh_iot &&
526 (vga_console_type == -1 || (type == vga_console_type)))
527 return (1);
528 return (0);
529 }
530
531 #define VGA_TS_BLANK 0x20
532
533 static int
534 vga_get_video(struct vga_config *vc)
535 {
536 return (vga_ts_read(&vc->hdl, mode) & VGA_TS_BLANK) == 0;
537 }
538
539 static void
540 vga_set_video(struct vga_config *vc, int state)
541 {
542 int val;
543
544 vga_ts_write(&vc->hdl, syncreset, 0x01);
545 if (state) { /* unblank screen */
546 val = vga_ts_read(&vc->hdl, mode);
547 vga_ts_write(&vc->hdl, mode, val & ~VGA_TS_BLANK);
548 #ifndef VGA_NO_VBLANK
549 val = vga_6845_read(&vc->hdl, mode);
550 vga_6845_write(&vc->hdl, mode, val | 0x80);
551 #endif
552 } else { /* blank screen */
553 val = vga_ts_read(&vc->hdl, mode);
554 vga_ts_write(&vc->hdl, mode, val | VGA_TS_BLANK);
555 #ifndef VGA_NO_VBLANK
556 val = vga_6845_read(&vc->hdl, mode);
557 vga_6845_write(&vc->hdl, mode, val & ~0x80);
558 #endif
559 }
560 vga_ts_write(&vc->hdl, syncreset, 0x03);
561 }
562
563 int
564 vga_raster_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
565 {
566 struct vga_config *vc = v;
567 const struct vga_funcs *vf = vc->vc_funcs;
568
569 switch (cmd) {
570 case WSDISPLAYIO_GTYPE:
571 *(int *)data = vc->vc_type;
572 return 0;
573
574 case WSDISPLAYIO_GINFO:
575 /* XXX should get detailed hardware information here */
576 return EPASSTHROUGH;
577
578 case WSDISPLAYIO_GVIDEO:
579 #if 1
580 *(int *)data = (vga_get_video(vc) ? WSDISPLAYIO_VIDEO_ON :
581 WSDISPLAYIO_VIDEO_OFF);
582 return 0;
583 #endif
584
585 case WSDISPLAYIO_SVIDEO:
586 #if 1
587 vga_set_video(vc, *(int *)data == WSDISPLAYIO_VIDEO_ON);
588 return 0;
589 #endif
590
591 case WSDISPLAYIO_GETCMAP:
592 case WSDISPLAYIO_PUTCMAP:
593 case WSDISPLAYIO_GCURPOS:
594 case WSDISPLAYIO_SCURPOS:
595 case WSDISPLAYIO_GCURMAX:
596 case WSDISPLAYIO_GCURSOR:
597 case WSDISPLAYIO_SCURSOR:
598 /* NONE of these operations are by the generic VGA driver. */
599 return EPASSTHROUGH;
600 }
601
602 if (vc->vc_funcs == NULL)
603 return (EPASSTHROUGH);
604
605 if (vf->vf_ioctl == NULL)
606 return (EPASSTHROUGH);
607
608 return ((*vf->vf_ioctl)(v, cmd, data, flag, p));
609
610 }
611
612 static paddr_t
613 vga_raster_mmap(void *v, off_t offset, int prot)
614 {
615 struct vga_config *vc = v;
616 const struct vga_funcs *vf = vc->vc_funcs;
617
618 if (vc->vc_funcs == NULL)
619 return (-1);
620
621 if (vf->vf_mmap == NULL)
622 return (-1);
623
624 return ((*vf->vf_mmap)(v, offset, prot));
625 }
626
627 int
628 vga_raster_alloc_screen(void *v, const struct wsscreen_descr *type,
629 void **cookiep, int *curxp, int *curyp, long *defattrp)
630 {
631 struct vga_config *vc = v;
632 struct vgascreen *scr;
633
634 if (vc->nscreens == 1) {
635 vc->screens.lh_first->mem = boot_scrmem;
636 }
637
638 scr = malloc(sizeof(struct vgascreen), M_DEVBUF, M_WAITOK);
639 vga_raster_init_screen(vc, scr, type, vc->nscreens == 0, defattrp);
640
641 if (vc->nscreens == 1) {
642 scr->active = 1;
643 vc->active = scr;
644 vc->currenttype = type;
645 } else {
646 scr->mem = malloc(sizeof(struct vga_scrmem) *
647 type->ncols * type->nrows, M_DEVBUF, M_WAITOK);
648 vga_raster_eraserows(scr, 0, type->nrows, *defattrp);
649 }
650
651 *cookiep = scr;
652 *curxp = scr->cursorcol;
653 *curyp = scr->cursorrow;
654
655 return (0);
656 }
657
658 void
659 vga_raster_free_screen(void *v, void *cookie)
660 {
661 struct vgascreen *vs = cookie;
662 struct vga_config *vc = vs->cfg;
663
664 LIST_REMOVE(vs, next);
665 if (vs != &vga_console_screen)
666 free(vs, M_DEVBUF);
667 else
668 panic("vga_raster_free_screen: console");
669
670 if (vc->active == vs)
671 vc->active = 0;
672 }
673
674 int
675 vga_raster_show_screen(void *v, void *cookie, int waitok,
676 void (*cb)(void *, int, int), void *cbarg)
677 {
678 struct vgascreen *scr = cookie, *oldscr;
679 struct vga_config *vc = scr->cfg;
680
681 oldscr = vc->active; /* can be NULL! */
682 if (scr == oldscr) {
683 return (0);
684 }
685
686 vc->wantedscreen = cookie;
687 vc->switchcb = cb;
688 vc->switchcbarg = cbarg;
689 if (cb) {
690 callout_reset(&vc->vc_switch_callout, 0,
691 (void(*)(void *))vga_switch_screen, vc);
692 return (EAGAIN);
693 }
694
695 vga_switch_screen(vc);
696 return (0);
697 }
698
699 void
700 vga_switch_screen(struct vga_config *vc)
701 {
702 struct vgascreen *scr, *oldscr;
703 struct vga_handle *vh = &vc->hdl;
704 const struct wsscreen_descr *type;
705
706 scr = vc->wantedscreen;
707 if (!scr) {
708 printf("vga_switch_screen: disappeared\n");
709 (*vc->switchcb)(vc->switchcbarg, EIO, 0);
710 return;
711 }
712 type = scr->type;
713 oldscr = vc->active; /* can be NULL! */
714 #ifdef DIAGNOSTIC
715 if (oldscr) {
716 if (!oldscr->active)
717 panic("vga_raster_show_screen: not active");
718 if (oldscr->type != vc->currenttype)
719 panic("vga_raster_show_screen: bad type");
720 }
721 #endif
722 if (scr == oldscr) {
723 return;
724 }
725 #ifdef DIAGNOSTIC
726 if (scr->active)
727 panic("vga_raster_show_screen: active");
728 #endif
729
730 if (oldscr)
731 oldscr->active = 0;
732
733 if (vc->currenttype != type) {
734 vga_raster_setscreentype(vc, type);
735 vc->currenttype = type;
736 }
737
738 scr->dispoffset = scr->mindispoffset;
739
740 if (!oldscr || (scr->dispoffset != oldscr->dispoffset)) {
741 vga_6845_write(vh, startadrh, scr->dispoffset >> 8);
742 vga_6845_write(vh, startadrl, scr->dispoffset);
743 }
744
745 /* Clear the entire screen. */
746 vga_gdc_write(vh, mode, 0x02);
747 bus_space_set_region_4(vh->vh_memt, vh->vh_allmemh, 0, 0, 0x2000);
748
749 scr->active = 1;
750 vga_restore_screen(scr, type, scr->mem);
751
752 vc->active = scr;
753
754 vga_raster_cursor(scr, scr->cursoron, scr->cursorrow, scr->cursorcol);
755
756 vc->wantedscreen = 0;
757 if (vc->switchcb)
758 (*vc->switchcb)(vc->switchcbarg, 0, 0);
759 }
760
761 static int
762 vga_raster_load_font(void *v, void *id, struct wsdisplay_font *data)
763 {
764 /* XXX */
765
766 return (0);
767 }
768
769 void
770 vga_raster_setup_font(struct vga_config *vc, struct vgascreen *scr)
771 {
772 struct vga_raster_font *vf;
773 struct wsdisplay_font *wf;
774 int cookie;
775
776 LIST_FOREACH(vf, &vc->vc_fontlist, next) {
777 if (wsfont_matches(vf->font, 0, 0, scr->type->fontheight, 0)) {
778 LIST_INSERT_HEAD(&scr->fontset, vf, next);
779 return;
780 }
781 }
782
783 cookie = wsfont_find(0, 0, scr->type->fontheight, 0,
784 WSDISPLAY_FONTORDER_L2R, 0);
785 if (cookie == -1)
786 return;
787
788 if (wsfont_lock(cookie, &wf))
789 return;
790
791 vf = malloc(sizeof(struct vga_raster_font), M_DEVBUF, M_NOWAIT);
792 if (!vf) {
793 wsfont_unlock(cookie);
794 return;
795 }
796
797 vf->font = wf;
798 LIST_INSERT_HEAD(&scr->fontset, vf, next);
799 }
800
801 void
802 vga_setup_regs(struct videomode *mode, struct vga_moderegs *regs)
803 {
804 int i;
805 int depth = 4; /* XXXBJY hardcoded for now */
806 int palette[16] = {
807 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
808 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
809 };
810
811 /*
812 * Compute hsync and vsync polarity.
813 */
814 if ((mode->flags & (VID_PHSYNC | VID_NHSYNC))
815 && (mode->flags & (VID_PVSYNC | VID_NVSYNC))) {
816 regs->miscout = 0x23;
817 if (mode->flags & VID_NHSYNC)
818 regs->miscout |= 0x40;
819 if (mode->flags & VID_NVSYNC)
820 regs->miscout |= 0x80;
821 } else {
822 if (mode->flags & VID_DBLSCAN)
823 mode->vdisplay *= 2;
824 if (mode->vdisplay < 400)
825 regs->miscout = 0xa3;
826 if (mode->vdisplay < 480)
827 regs->miscout = 0x63;
828 if (mode->vdisplay < 768)
829 regs->miscout = 0xe3;
830 else
831 regs->miscout = 0x23;
832 }
833
834 /*
835 * Time sequencer
836 */
837 if (depth == 4)
838 regs->ts[0] = 0x02;
839 else
840 regs->ts[0] = 0x00;
841 if (mode->flags & VID_CLKDIV2)
842 regs->ts[1] = 0x09;
843 else
844 regs->ts[1] = 0x01;
845 regs->ts[2] = 0x0f;
846 regs->ts[3] = 0x00;
847 if (depth < 8)
848 regs->ts[4] = 0x06;
849 else
850 regs->ts[4] = 0x0e;
851
852 /*
853 * CRTC controller
854 */
855 regs->crtc[0] = (mode->htotal >> 3) - 5;
856 regs->crtc[1] = (mode->hdisplay >> 3) - 1;
857 regs->crtc[2] = (mode->hsync_start >> 3) - 1;
858 regs->crtc[3] = (((mode->hsync_end >> 3) - 1) & 0x1f) | 0x80;
859 regs->crtc[4] = mode->hsync_start >> 3;
860 regs->crtc[5] = ((((mode->hsync_end >> 3) - 1) & 0x20) << 2)
861 | (((mode->hsync_end >> 3)) & 0x1f);
862 regs->crtc[6] = (mode->vtotal - 2) & 0xff;
863 regs->crtc[7] = (((mode->vtotal - 2) & 0x100) >> 8)
864 | (((mode->vdisplay - 1) & 0x100) >> 7)
865 | ((mode->vsync_start & 0x100) >> 6)
866 | (((mode->vsync_start - 1) & 0x100) >> 5)
867 | 0x10
868 | (((mode->vtotal - 2) & 0x200) >> 4)
869 | (((mode->vdisplay - 1) & 0x200) >> 3)
870 | ((mode->vsync_start & 0x200) >> 2);
871 regs->crtc[8] = 0x00;
872 regs->crtc[9] = (((mode->vsync_start - 1) & 0x200) >> 4) | 0x40;
873 if (mode->flags & VID_DBLSCAN)
874 regs->crtc[9] |= 0x80;
875 regs->crtc[10] = 0x00;
876 regs->crtc[11] = 0x00;
877 regs->crtc[12] = 0x00;
878 regs->crtc[13] = 0x00;
879 regs->crtc[14] = 0x00;
880 regs->crtc[15] = 0x00;
881 regs->crtc[16] = mode->vsync_start & 0xff;
882 regs->crtc[17] = (mode->vsync_end & 0x0f) | 0x20;
883 regs->crtc[18] = (mode->vdisplay - 1) & 0xff;
884 regs->crtc[19] = mode->hdisplay >> 4; /* XXXBJY */
885 regs->crtc[20] = 0x00;
886 regs->crtc[21] = (mode->vsync_start - 1) & 0xff;
887 regs->crtc[22] = (mode->vsync_end - 1) & 0xff;
888 if (depth < 8)
889 regs->crtc[23] = 0xe3;
890 else
891 regs->crtc[23] = 0xc3;
892 regs->crtc[24] = 0xff;
893
894 /*
895 * Graphics display controller
896 */
897 regs->gdc[0] = 0x00;
898 regs->gdc[1] = 0x00;
899 regs->gdc[2] = 0x00;
900 regs->gdc[3] = 0x00;
901 regs->gdc[4] = 0x00;
902 if (depth == 4)
903 regs->gdc[5] = 0x02;
904 else
905 regs->gdc[5] = 0x40;
906 regs->gdc[6] = 0x01;
907 regs->gdc[7] = 0x0f;
908 regs->gdc[8] = 0xff;
909
910 /*
911 * Attribute controller
912 */
913 /* Set palette registers. */
914 for (i = 0; i < 16; i++)
915 regs->atc[i] = palette[i];
916 if (depth == 4)
917 regs->atc[16] = 0x01; /* XXXBJY was 0x81 in XFree86 */
918 else
919 regs->atc[16] = 0x41;
920 regs->atc[17] = 0x00; /* XXXBJY just a guess */
921 regs->atc[18] = 0x0f;
922 regs->atc[19] = 0x00;
923 regs->atc[20] = 0x00;
924 }
925
926 void
927 vga_set_mode(struct vga_handle *vh, struct vga_moderegs *regs)
928 {
929 int i;
930
931 /* Disable display. */
932 vga_ts_write(vh, mode, vga_ts_read(vh, mode) | 0x20);
933
934 /* Write misc output register. */
935 bus_space_write_1(vh->vh_iot, vh->vh_ioh_vga, VGA_MISC_DATAW,
936 regs->miscout);
937
938 /* Set synchronous reset. */
939 vga_ts_write(vh, syncreset, 0x01);
940 vga_ts_write(vh, mode, regs->ts[1] | 0x20);
941 for (i = 2; i < VGA_TS_NREGS; i++)
942 _vga_ts_write(vh, i, regs->ts[i]);
943 /* Clear synchronous reset. */
944 vga_ts_write(vh, syncreset, 0x03);
945
946 /* Unprotect CRTC registers 0-7. */
947 _vga_crtc_write(vh, 17, _vga_crtc_read(vh, 17) & 0x7f);
948 /* Write CRTC registers. */
949 for (i = 0; i < VGA_CRTC_NREGS; i++)
950 _vga_crtc_write(vh, i, regs->crtc[i]);
951
952 /* Write graphics display registers. */
953 for (i = 0; i < VGA_GDC_NREGS; i++)
954 _vga_gdc_write(vh, i, regs->gdc[i]);
955
956 /* Write attribute controller registers. */
957 for (i = 0; i < VGA_ATC_NREGS; i++)
958 _vga_attr_write(vh, i, regs->atc[i]);
959
960 /* Enable display. */
961 vga_ts_write(vh, mode, vga_ts_read(vh, mode) & 0xdf);
962 }
963
964 void
965 vga_raster_cursor_init(struct vgascreen *scr, int existing)
966 {
967 struct vga_handle *vh = scr->hdl;
968 bus_space_tag_t memt;
969 bus_space_handle_t memh;
970 int off;
971
972 if (existing) {
973 /*
974 * This is the first screen. At this point, scr->active is
975 * false, so we can't use vga_raster_cursor() to do this.
976 */
977 memt = vh->vh_memt;
978 memh = vh->vh_memh;
979 off = (scr->cursorrow * scr->type->ncols + scr->cursorcol) +
980 scr->dispoffset / 8;
981
982 scr->cursortmp = scr->mem[off];
983 vga_raster_putchar(scr, scr->cursorrow, scr->cursorcol,
984 scr->cursortmp.ch, scr->cursortmp.attr ^ 0x77);
985 } else {
986 scr->cursortmp.ch = 0;
987 scr->cursortmp.attr = 0;
988 scr->cursortmp.second = 0;
989 scr->cursortmp.enc = WSDISPLAY_FONTENC_IBM;
990 }
991
992 scr->cursoron = 1;
993 }
994
995 void
996 vga_raster_cursor(void *id, int on, int row, int col)
997 {
998 struct vgascreen *scr = id;
999 int off, tmp;
1000
1001 /* Remove old cursor image */
1002 if (scr->cursoron) {
1003 off = scr->cursorrow * scr->type->ncols + scr->cursorcol;
1004 if (scr->active) {
1005 tmp = scr->encoding;
1006 scr->encoding = scr->cursortmp.enc;
1007 if (scr->cursortmp.second)
1008 vga_raster_putchar(id, scr->cursorrow,
1009 scr->cursorcol - 1, scr->cursortmp.ch,
1010 scr->cursortmp.attr);
1011 else
1012 vga_raster_putchar(id, scr->cursorrow,
1013 scr->cursorcol, scr->cursortmp.ch,
1014 scr->cursortmp.attr);
1015 scr->encoding = tmp;
1016 }
1017 }
1018
1019 scr->cursorrow = row;
1020 scr->cursorcol = col;
1021
1022 if ((scr->cursoron = on) == 0)
1023 return;
1024
1025 off = scr->cursorrow * scr->type->ncols + scr->cursorcol;
1026 scr->cursortmp = scr->mem[off];
1027 if (scr->active) {
1028 tmp = scr->encoding;
1029 scr->encoding = scr->cursortmp.enc;
1030 if (scr->cursortmp.second)
1031 vga_raster_putchar(id, scr->cursorrow,
1032 scr->cursorcol - 1, scr->cursortmp.ch,
1033 scr->cursortmp.attr ^ 0x77);
1034 else
1035 vga_raster_putchar(id, scr->cursorrow,
1036 scr->cursorcol, scr->cursortmp.ch,
1037 scr->cursortmp.attr ^ 0x77);
1038 scr->encoding = tmp;
1039 }
1040 }
1041
1042 static int
1043 vga_raster_mapchar(void *id, int uni, u_int *index)
1044 {
1045 struct vgascreen *scr = id;
1046
1047 if (scr->encoding == WSDISPLAY_FONTENC_IBM)
1048 return pcdisplay_mapchar(id, uni, index);
1049 else {
1050 *index = uni;
1051 return 5;
1052 }
1053 }
1054
1055 void
1056 vga_raster_putchar(void *id, int row, int col, u_int c, long attr)
1057 {
1058 struct vgascreen *scr = id;
1059 int off;
1060 struct vga_raster_font *fs;
1061 u_int tmp_ch;
1062
1063 off = row * scr->type->ncols + col;
1064
1065 LIST_FOREACH(fs, &scr->fontset, next) {
1066 if ((scr->encoding == fs->font->encoding) &&
1067 (c >= fs->font->firstchar) &&
1068 (c < fs->font->firstchar + fs->font->numchars) &&
1069 (scr->type->fontheight == fs->font->fontheight)) {
1070 if (scr->active) {
1071 tmp_ch = c - fs->font->firstchar;
1072 _vga_raster_putchar(scr, row, col, tmp_ch,
1073 attr, fs);
1074 }
1075
1076 scr->mem[off].ch = c;
1077 scr->mem[off].attr = attr;
1078 scr->mem[off].second = 0;
1079 scr->mem[off].enc = fs->font->encoding;
1080
1081 if (fs->font->stride == 2) {
1082 scr->mem[off + 1].ch = c;
1083 scr->mem[off + 1].attr = attr;
1084 scr->mem[off + 1].second = 1;
1085 scr->mem[off + 1].enc = fs->font->encoding;
1086 }
1087
1088 return;
1089 }
1090 }
1091
1092 /*
1093 * No match found.
1094 */
1095 if (scr->active)
1096 /* Put a single width space character no matter what the
1097 actual width of the character is. */
1098 _vga_raster_putchar(scr, row, col, 0x20, attr,
1099 &vga_console_fontset_ascii);
1100 scr->mem[off].ch = c;
1101 scr->mem[off].attr = attr;
1102 scr->mem[off].second = 0;
1103 scr->mem[off].enc = WSDISPLAY_FONTENC_IBM;
1104 }
1105
1106 static void
1107 _vga_raster_putchar(void *id, int row, int col, u_int c, long attr,
1108 struct vga_raster_font *fs)
1109 {
1110 struct vgascreen *scr = id;
1111 struct vga_handle *vh = scr->hdl;
1112 bus_space_tag_t memt = vh->vh_memt;
1113 bus_space_handle_t memh = vh->vh_memh;
1114 int i;
1115 int rasoff, rasoff2;
1116 int fheight = scr->type->fontheight;
1117 volatile u_int8_t dummy, pattern;
1118 u_int8_t fgcolor, bgcolor;
1119
1120 rasoff = scr->dispoffset + row * scr->type->ncols * fheight + col;
1121 rasoff2 = rasoff;
1122
1123 #if 0
1124 bgcolor = bgansitopc[attr >> 4];
1125 fgcolor = fgansitopc[attr & 0x0f];
1126 #else
1127 bgcolor = ((attr >> 4) & 0x0f);
1128 fgcolor = attr & 0x0f;
1129 #endif
1130
1131 if (fs->font->stride == 1) {
1132 /* Paint background. */
1133 vga_gdc_write(vh, mode, 0x02);
1134 for (i = 0; i < fheight; i++) {
1135 bus_space_write_1(memt, memh, rasoff, bgcolor);
1136 rasoff += scr->type->ncols;
1137 }
1138
1139 /* Draw a single width character. */
1140 vga_gdc_write(vh, mode, 0x03);
1141 vga_gdc_write(vh, setres, fgcolor);
1142 for (i = 0; i < fheight; i++) {
1143 pattern = ((u_int8_t *)fs->font->data)[c * fheight + i];
1144 /* When pattern is 0, skip output for speed-up. */
1145 if (pattern != 0) {
1146 dummy = bus_space_read_1(memt, memh, rasoff2);
1147 bus_space_write_1(memt, memh, rasoff2, pattern);
1148 }
1149 rasoff2 += scr->type->ncols;
1150 }
1151 } else if (fs->font->stride == 2) {
1152 /* Paint background. */
1153 vga_gdc_write(vh, mode, 0x02);
1154 for (i = 0; i < fheight; i++) {
1155 bus_space_write_1(memt, memh, rasoff, bgcolor);
1156 bus_space_write_1(memt, memh, rasoff + 1, bgcolor);
1157 rasoff += scr->type->ncols;
1158 }
1159
1160 /* Draw a double width character. */
1161 vga_gdc_write(vh, mode, 0x03);
1162 vga_gdc_write(vh, setres, fgcolor);
1163 for (i = 0; i < fheight; i++) {
1164 pattern = ((u_int8_t *)fs->font->data)
1165 [(c * fheight + i) * 2];
1166 if (pattern != 0) {
1167 dummy = bus_space_read_1(memt, memh, rasoff2);
1168 bus_space_write_1(memt, memh, rasoff2, pattern);
1169 }
1170 pattern = ((u_int8_t *)fs->font->data)
1171 [(c * fheight + i) * 2 + 1];
1172 if (pattern != 0) {
1173 rasoff2++;
1174 dummy = bus_space_read_1(memt, memh, rasoff2);
1175 bus_space_write_1(memt, memh, rasoff2, pattern);
1176 rasoff2--;
1177 }
1178 rasoff2 += scr->type->ncols;
1179 }
1180 }
1181 }
1182
1183 void
1184 vga_raster_copycols(void *id, int row, int srccol, int dstcol, int ncols)
1185 {
1186 struct vgascreen *scr = id;
1187 struct vga_handle *vh = scr->hdl;
1188 bus_space_tag_t memt = vh->vh_memt;
1189 bus_space_handle_t memh = vh->vh_memh;
1190 bus_size_t srcoff, dstoff;
1191 bus_size_t rassrcoff, rasdstoff;
1192 int i;
1193 int fheight = scr->type->fontheight;
1194
1195 srcoff = row * scr->type->ncols + srccol;
1196 dstoff = row * scr->type->ncols + dstcol;
1197 rassrcoff = scr->dispoffset + row * scr->type->ncols * fheight + srccol;
1198 rasdstoff = scr->dispoffset + row * scr->type->ncols * fheight + dstcol;
1199
1200 memcpy(&scr->mem[dstoff], &scr->mem[srcoff],
1201 ncols * sizeof(struct vga_scrmem));
1202
1203 vga_gdc_write(vh, mode, 0x01);
1204 if (scr->active) {
1205 for (i = 0; i < fheight; i++) {
1206 bus_space_copy_region_1(memt, memh,
1207 rassrcoff + i * scr->type->ncols, memh,
1208 rasdstoff + i * scr->type->ncols, ncols);
1209 }
1210 }
1211 }
1212
1213 void
1214 vga_raster_erasecols(void *id, int row, int startcol, int ncols, long fillattr)
1215 {
1216 struct vgascreen *scr = id;
1217 int i;
1218
1219 if (scr->active == 0)
1220 return;
1221
1222 for (i = startcol; i < startcol + ncols; i++)
1223 vga_raster_putchar(id, row, i, ' ', fillattr);
1224 }
1225
1226 void
1227 vga_raster_copyrows(void *id, int srcrow, int dstrow, int nrows)
1228 {
1229 struct vgascreen *scr = id;
1230 struct vga_handle *vh = scr->hdl;
1231 bus_space_tag_t memt = vh->vh_memt;
1232 bus_space_handle_t memh = vh->vh_memh;
1233 int ncols;
1234 bus_size_t srcoff, dstoff;
1235 bus_size_t rassrcoff, rasdstoff;
1236 int fheight;
1237
1238 ncols = scr->type->ncols;
1239 fheight = scr->type->fontheight;
1240
1241 srcoff = srcrow * ncols;
1242 dstoff = dstrow * ncols;
1243 rassrcoff = srcoff * fheight;
1244 rasdstoff = dstoff * fheight;
1245
1246 if (scr->active) {
1247 vga_gdc_write(vh, mode, 0x01);
1248 if (dstrow == 0 && (srcrow + nrows == scr->type->nrows)) {
1249 int cursoron = scr->cursoron;
1250
1251 if (cursoron)
1252 /* Disable cursor. */
1253 vga_raster_cursor(scr, 0,
1254 scr->cursorrow, scr->cursorcol);
1255
1256 /* scroll up whole screen */
1257 if ((scr->dispoffset + srcrow * ncols * fheight)
1258 <= scr->maxdispoffset)
1259 scr->dispoffset += srcrow * ncols * fheight;
1260 else {
1261 bus_space_copy_region_1(memt, memh,
1262 scr->dispoffset + rassrcoff,
1263 memh, scr->mindispoffset,
1264 nrows * ncols * fheight);
1265 scr->dispoffset = scr->mindispoffset;
1266 }
1267 vga_6845_write(vh, startadrh, scr->dispoffset >> 8);
1268 vga_6845_write(vh, startadrl, scr->dispoffset);
1269
1270 if (cursoron)
1271 /* Enable cursor. */
1272 vga_raster_cursor(scr, 1, scr->cursorrow,
1273 scr->cursorcol);
1274 } else
1275 bus_space_copy_region_1(memt, memh,
1276 scr->dispoffset + rassrcoff, memh,
1277 scr->dispoffset + rasdstoff,
1278 nrows * ncols * fheight);
1279 }
1280 memcpy(&scr->mem[dstoff], &scr->mem[srcoff],
1281 nrows * ncols * sizeof(struct vga_scrmem));
1282 }
1283
1284 void
1285 vga_raster_eraserows(void *id, int startrow, int nrows, long fillattr)
1286 {
1287 struct vgascreen *scr = id;
1288 struct vga_handle *vh = scr->hdl;
1289 bus_space_tag_t memt = vh->vh_memt;
1290 bus_space_handle_t memh = vh->vh_memh;
1291 bus_size_t off, count;
1292 bus_size_t rasoff, rascount;
1293 int i;
1294
1295 off = startrow * scr->type->ncols;
1296 count = nrows * scr->type->ncols;
1297 rasoff = off * scr->type->fontheight;
1298 rascount = count * scr->type->fontheight;
1299
1300 if (scr->active) {
1301 /* Paint background. */
1302 vga_gdc_write(vh, mode, 0x02);
1303 if (scr->type->ncols % 4 == 0)
1304 /* We can speed up I/O */
1305 for (i = rasoff; i < rasoff + rascount; i += 4)
1306 bus_space_write_4(memt, memh,
1307 scr->dispoffset + i, fillattr >> 4);
1308 else
1309 for (i = rasoff; i < rasoff + rascount; i += 2)
1310 bus_space_write_2(memt, memh,
1311 scr->dispoffset + i, fillattr >> 4);
1312 }
1313 for (i = 0; i < count; i++) {
1314 scr->mem[off + i].ch = ' ';
1315 scr->mem[off + i].attr = fillattr;
1316 scr->mem[off + i].second = 0;
1317 scr->mem[off + i].enc = WSDISPLAY_FONTENC_IBM;
1318 }
1319 }
1320
1321 static int
1322 vga_raster_allocattr(void *id, int fg, int bg, int flags, long *attrp)
1323 {
1324 struct vgascreen *scr = id;
1325 struct vga_config *vc = scr->cfg;
1326
1327 if (vc->hdl.vh_mono) {
1328 if (flags & WSATTR_WSCOLORS)
1329 return (EINVAL);
1330 if (flags & WSATTR_REVERSE)
1331 *attrp = 0x70;
1332 else
1333 *attrp = 0x07;
1334 if (flags & WSATTR_UNDERLINE)
1335 *attrp |= FG_UNDERLINE;
1336 if (flags & WSATTR_HILIT)
1337 *attrp |= FG_INTENSE;
1338 } else {
1339 if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE))
1340 return (EINVAL);
1341 if (flags & WSATTR_WSCOLORS)
1342 *attrp = fgansitopc[fg] | bgansitopc[bg];
1343 else
1344 *attrp = 7;
1345 if (flags & WSATTR_HILIT)
1346 *attrp += 8;
1347 }
1348 if (flags & WSATTR_BLINK)
1349 *attrp |= FG_BLINK;
1350 return (0);
1351 }
1352
1353 void
1354 vga_restore_screen(struct vgascreen *scr,
1355 const struct wsscreen_descr *type, struct vga_scrmem *mem)
1356 {
1357 int i, j, off, tmp;
1358
1359 tmp = scr->encoding;
1360 for (i = 0; i < type->nrows; i++) {
1361 for (j = 0; j < type->ncols; j++) {
1362 off = i * type->ncols + j;
1363 if (mem[off].second != 1) {
1364 scr->encoding = mem[off].enc;
1365 vga_raster_putchar(scr, i, j, mem[off].ch,
1366 mem[off].attr);
1367 }
1368 }
1369 }
1370 scr->encoding = tmp;
1371 }
1372
1373 void
1374 vga_raster_setscreentype(struct vga_config *vc,
1375 const struct wsscreen_descr *type)
1376 {
1377 int i;
1378 struct vga_moderegs moderegs;
1379 struct vga_handle *vh = &vc->hdl;
1380
1381 for (i = 0; i < sizeof(vga_console_modes) /
1382 sizeof(vga_console_modes[0]); i++) {
1383 if (memcmp((struct videomode *)type->modecookie,
1384 &vga_console_modes[i], sizeof(struct videomode)) == 0) {
1385 vga_setup_regs(&vga_console_modes[i], &moderegs);
1386 vga_set_mode(vh, &moderegs);
1387 }
1388 }
1389 }
1390