This source file includes following definitions.
- vga_common_probe
- vga_selectfont
- vga_init_screen
- vga_init
- vga_common_attach
- vga_extended_attach
- vga_cnattach
- vga_is_console
- vga_ioctl
- vga_mmap
- vga_alloc_screen
- vga_free_screen
- vga_setfont
- vga_show_screen
- vga_doswitch
- vga_load_font
- vga_scrollback
- vga_alloc_attr
- vga_unpack_attr
- vga_copyrows
- vga_pcvt_mapchar
- _vga_mapchar
- vga_mapchar
- vga_putchar
- vga_burner
- vga_getchar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 #include "vga.h"
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/device.h>
37 #include <sys/malloc.h>
38 #include <sys/queue.h>
39 #include <machine/bus.h>
40
41 #include <dev/ic/mc6845reg.h>
42 #include <dev/ic/pcdisplayvar.h>
43 #include <dev/ic/vgareg.h>
44 #include <dev/ic/vgavar.h>
45
46 #include <dev/wscons/wsdisplayvar.h>
47 #include <dev/wscons/wsconsio.h>
48 #include <dev/wscons/unicode.h>
49
50 #include <dev/ic/pcdisplay.h>
51
52 static struct vgafont {
53 char name[WSFONT_NAME_SIZE];
54 int height;
55 int encoding;
56 #ifdef notyet
57 int firstchar, numchars;
58 #endif
59 int slot;
60 } vga_builtinfont = {
61 "builtin",
62 16,
63 WSDISPLAY_FONTENC_IBM,
64 #ifdef notyet
65 0, 256,
66 #endif
67 0
68 };
69
70 struct vgascreen {
71 struct pcdisplayscreen pcs;
72
73 LIST_ENTRY(vgascreen) next;
74
75 struct vga_config *cfg;
76
77
78 struct vgafont *fontset1, *fontset2;
79
80
81
82 int mindispoffset, maxdispoffset;
83 int vga_rollover;
84 };
85
86 int vgaconsole, vga_console_type, vga_console_attached;
87 struct vgascreen vga_console_screen;
88 struct vga_config vga_console_vc;
89
90 int vga_selectfont(struct vga_config *, struct vgascreen *,
91 const char *, const char *);
92 void vga_init_screen(struct vga_config *, struct vgascreen *,
93 const struct wsscreen_descr *, int, long *);
94 void vga_init(struct vga_config *, bus_space_tag_t, bus_space_tag_t);
95 void vga_setfont(struct vga_config *, struct vgascreen *);
96
97 int vga_mapchar(void *, int, unsigned int *);
98 void vga_putchar(void *, int, int, u_int, long);
99 int vga_alloc_attr(void *, int, int, int, long *);
100 void vga_copyrows(void *, int, int, int);
101 void vga_unpack_attr(void *, long, int *, int *, int *);
102
103 static const struct wsdisplay_emulops vga_emulops = {
104 pcdisplay_cursor,
105 vga_mapchar,
106 vga_putchar,
107 pcdisplay_copycols,
108 pcdisplay_erasecols,
109 vga_copyrows,
110 pcdisplay_eraserows,
111 vga_alloc_attr,
112 vga_unpack_attr
113 };
114
115
116
117
118 static const unsigned char fgansitopc[] = {
119 #ifdef __alpha__
120
121
122
123
124
125 FG_BLACK, FG_BLUE, FG_GREEN, FG_CYAN, FG_RED,
126 FG_MAGENTA, FG_BROWN, FG_LIGHTGREY
127 #else
128 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
129 FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
130 #endif
131 }, bgansitopc[] = {
132 #ifdef __alpha__
133 BG_BLACK, BG_BLUE, BG_GREEN, BG_CYAN, BG_RED,
134 BG_MAGENTA, BG_BROWN, BG_LIGHTGREY
135 #else
136 BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
137 BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
138 #endif
139 };
140
141
142
143
144 static const u_int8_t pctoansi[] = {
145 #ifdef __alpha__
146 WSCOL_BLACK, WSCOL_RED, WSCOL_GREEN, WSCOL_BROWN,
147 WSCOL_BLUE, WSCOL_MAGENTA, WSCOL_CYAN, WSCOL_WHITE
148 #else
149 WSCOL_BLACK, WSCOL_BLUE, WSCOL_GREEN, WSCOL_CYAN,
150 WSCOL_RED, WSCOL_MAGENTA, WSCOL_BROWN, WSCOL_WHITE
151 #endif
152 };
153
154
155 const struct wsscreen_descr vga_stdscreen = {
156 "80x25", 80, 25,
157 &vga_emulops,
158 8, 16,
159 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
160 }, vga_stdscreen_mono = {
161 "80x25", 80, 25,
162 &vga_emulops,
163 8, 16,
164 WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
165 }, vga_stdscreen_bf = {
166 "80x25bf", 80, 25,
167 &vga_emulops,
168 8, 16,
169 WSSCREEN_WSCOLORS | WSSCREEN_BLINK
170 }, vga_40lscreen = {
171 "80x40", 80, 40,
172 &vga_emulops,
173 8, 10,
174 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
175 }, vga_40lscreen_mono = {
176 "80x40", 80, 40,
177 &vga_emulops,
178 8, 10,
179 WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
180 }, vga_40lscreen_bf = {
181 "80x40bf", 80, 40,
182 &vga_emulops,
183 8, 10,
184 WSSCREEN_WSCOLORS | WSSCREEN_BLINK
185 }, vga_50lscreen = {
186 "80x50", 80, 50,
187 &vga_emulops,
188 8, 8,
189 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK
190 }, vga_50lscreen_mono = {
191 "80x50", 80, 50,
192 &vga_emulops,
193 8, 8,
194 WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE
195 }, vga_50lscreen_bf = {
196 "80x50bf", 80, 50,
197 &vga_emulops,
198 8, 8,
199 WSSCREEN_WSCOLORS | WSSCREEN_BLINK
200 };
201
202 #define VGA_SCREEN_CANTWOFONTS(type) (!((type)->capabilities & WSSCREEN_HILIT))
203
204 const struct wsscreen_descr *_vga_scrlist[] = {
205 &vga_stdscreen,
206 &vga_stdscreen_bf,
207 &vga_40lscreen,
208 &vga_40lscreen_bf,
209 &vga_50lscreen,
210 &vga_50lscreen_bf,
211
212 }, *_vga_scrlist_mono[] = {
213 &vga_stdscreen_mono,
214 &vga_40lscreen_mono,
215 &vga_50lscreen_mono,
216
217 };
218
219 const struct wsscreen_list vga_screenlist = {
220 sizeof(_vga_scrlist) / sizeof(struct wsscreen_descr *),
221 _vga_scrlist
222 }, vga_screenlist_mono = {
223 sizeof(_vga_scrlist_mono) / sizeof(struct wsscreen_descr *),
224 _vga_scrlist_mono
225 };
226
227 int vga_ioctl(void *, u_long, caddr_t, int, struct proc *);
228 paddr_t vga_mmap(void *, off_t, int);
229 int vga_alloc_screen(void *, const struct wsscreen_descr *,
230 void **, int *, int *, long *);
231 void vga_free_screen(void *, void *);
232 int vga_show_screen(void *, void *, int,
233 void (*) (void *, int, int), void *);
234 int vga_load_font(void *, void *, struct wsdisplay_font *);
235 void vga_scrollback(void *, void *, int);
236 void vga_burner(void *v, u_int on, u_int flags);
237 int vga_getchar(void *, int, int, struct wsdisplay_charcell *);
238
239 void vga_doswitch(struct vga_config *);
240
241 const struct wsdisplay_accessops vga_accessops = {
242 vga_ioctl,
243 vga_mmap,
244 vga_alloc_screen,
245 vga_free_screen,
246 vga_show_screen,
247 vga_load_font,
248 vga_scrollback,
249 vga_getchar,
250 vga_burner
251 };
252
253
254
255
256
257 int
258 vga_common_probe(iot, memt)
259 bus_space_tag_t iot, memt;
260 {
261 bus_space_handle_t ioh_vga, ioh_6845, memh;
262 u_int8_t regval;
263 u_int16_t vgadata;
264 int gotio_vga, gotio_6845, gotmem, mono, rv;
265 int dispoffset;
266
267 gotio_vga = gotio_6845 = gotmem = rv = 0;
268
269 if (bus_space_map(iot, 0x3c0, 0x10, 0, &ioh_vga))
270 goto bad;
271 gotio_vga = 1;
272
273
274 regval = bus_space_read_1(iot, ioh_vga, 0xc);
275 mono = !(regval & 1);
276
277 if (bus_space_map(iot, (mono ? 0x3b0 : 0x3d0), 0x10, 0, &ioh_6845))
278 goto bad;
279 gotio_6845 = 1;
280
281 if (bus_space_map(memt, 0xa0000, 0x20000, 0, &memh))
282 goto bad;
283 gotmem = 1;
284
285 dispoffset = (mono ? 0x10000 : 0x18000);
286
287 vgadata = bus_space_read_2(memt, memh, dispoffset);
288 bus_space_write_2(memt, memh, dispoffset, 0xa55a);
289 if (bus_space_read_2(memt, memh, dispoffset) != 0xa55a)
290 goto bad;
291 bus_space_write_2(memt, memh, dispoffset, vgadata);
292
293
294
295
296
297
298
299 (void) bus_space_read_1(iot, ioh_6845, 10);
300 bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX,
301 20 | 0x20);
302 regval = bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR);
303
304 bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval ^ 0x0f);
305 bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX,
306 20 | 0x20);
307
308 if (bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR) != (regval ^ 0x0f))
309 goto bad;
310
311 bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval);
312
313 rv = 1;
314 bad:
315 if (gotio_vga)
316 bus_space_unmap(iot, ioh_vga, 0x10);
317 if (gotio_6845)
318 bus_space_unmap(iot, ioh_6845, 0x10);
319 if (gotmem)
320 bus_space_unmap(memt, memh, 0x20000);
321
322 return (rv);
323 }
324
325
326
327
328
329 #define vga_valid_primary_font(f) \
330 (f->encoding == WSDISPLAY_FONTENC_IBM || \
331 f->encoding == WSDISPLAY_FONTENC_ISO)
332
333 int
334 vga_selectfont(vc, scr, name1, name2)
335 struct vga_config *vc;
336 struct vgascreen *scr;
337 const char *name1, *name2;
338 {
339 const struct wsscreen_descr *type = scr->pcs.type;
340 struct vgafont *f1, *f2;
341 int i;
342
343 f1 = f2 = 0;
344
345 for (i = 0; i < 8; i++) {
346 struct vgafont *f = vc->vc_fonts[i];
347 if (!f || f->height != type->fontheight)
348 continue;
349 if (!f1 &&
350 vga_valid_primary_font(f) &&
351 (!name1 || !*name1 ||
352 !strncmp(name1, f->name, WSFONT_NAME_SIZE))) {
353 f1 = f;
354 continue;
355 }
356 if (!f2 &&
357 VGA_SCREEN_CANTWOFONTS(type) &&
358 (!name2 || !*name2 ||
359 !strncmp(name2, f->name, WSFONT_NAME_SIZE))) {
360 f2 = f;
361 continue;
362 }
363 }
364
365
366
367
368
369 if (f1 && (!name2 || !*name2 || f2)) {
370 #ifdef VGAFONTDEBUG
371 if (scr != &vga_console_screen || vga_console_attached) {
372 printf("vga (%s): font1=%s (slot %d)", type->name,
373 f1->name, f1->slot);
374 if (f2)
375 printf(", font2=%s (slot %d)",
376 f2->name, f2->slot);
377 printf("\n");
378 }
379 #endif
380 scr->fontset1 = f1;
381 scr->fontset2 = f2;
382 return (0);
383 }
384 return (ENXIO);
385 }
386
387 void
388 vga_init_screen(vc, scr, type, existing, attrp)
389 struct vga_config *vc;
390 struct vgascreen *scr;
391 const struct wsscreen_descr *type;
392 int existing;
393 long *attrp;
394 {
395 int cpos;
396 int res;
397
398 scr->cfg = vc;
399 scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl;
400 scr->pcs.type = type;
401 scr->pcs.active = 0;
402 scr->mindispoffset = 0;
403 scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2;
404
405 if (existing) {
406 cpos = vga_6845_read(&vc->hdl, cursorh) << 8;
407 cpos |= vga_6845_read(&vc->hdl, cursorl);
408
409
410 if (cpos < 0 || cpos >= type->nrows * type->ncols)
411 cpos = 0;
412
413 scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh) << 9;
414 scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl) << 1;
415
416
417 if (scr->pcs.dispoffset < scr->mindispoffset ||
418 scr->pcs.dispoffset > scr->maxdispoffset)
419 scr->pcs.dispoffset = scr->mindispoffset;
420 } else {
421 cpos = 0;
422 scr->pcs.dispoffset = scr->mindispoffset;
423 }
424 scr->pcs.visibleoffset = scr->pcs.dispoffset;
425 scr->vga_rollover = 0;
426
427 scr->pcs.vc_crow = cpos / type->ncols;
428 scr->pcs.vc_ccol = cpos % type->ncols;
429 pcdisplay_cursor_init(&scr->pcs, existing);
430
431 #ifdef __alpha__
432 if (!vc->hdl.vh_mono)
433
434
435
436 res = vga_alloc_attr(scr, WSCOL_WHITE, WSCOL_BLUE,
437 WSATTR_WSCOLORS, attrp);
438 else
439 #endif
440 res = vga_alloc_attr(scr, 0, 0, 0, attrp);
441 #ifdef DIAGNOSTIC
442 if (res)
443 panic("vga_init_screen: attribute botch");
444 #endif
445
446 scr->pcs.mem = NULL;
447
448 scr->fontset1 = scr->fontset2 = 0;
449 if (vga_selectfont(vc, scr, 0, 0)) {
450 if (scr == &vga_console_screen)
451 panic("vga_init_screen: no font");
452 else
453 printf("vga_init_screen: no font\n");
454 }
455
456 vc->nscreens++;
457 LIST_INSERT_HEAD(&vc->screens, scr, next);
458 }
459
460 void
461 vga_init(vc, iot, memt)
462 struct vga_config *vc;
463 bus_space_tag_t iot, memt;
464 {
465 struct vga_handle *vh = &vc->hdl;
466 u_int8_t mor;
467 int i;
468
469 vh->vh_iot = iot;
470 vh->vh_memt = memt;
471
472 if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga))
473 panic("vga_common_setup: couldn't map vga io");
474
475
476 mor = bus_space_read_1(vh->vh_iot, vh->vh_ioh_vga, 0xc);
477 vh->vh_mono = !(mor & 1);
478
479 if (bus_space_map(vh->vh_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0,
480 &vh->vh_ioh_6845))
481 panic("vga_common_setup: couldn't map 6845 io");
482
483 if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh))
484 panic("vga_common_setup: couldn't map memory");
485
486 if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh,
487 (vh->vh_mono ? 0x10000 : 0x18000), 0x8000,
488 &vh->vh_memh))
489 panic("vga_common_setup: mem subrange failed");
490
491 vc->nscreens = 0;
492 LIST_INIT(&vc->screens);
493 vc->active = NULL;
494 vc->currenttype = vh->vh_mono ? &vga_stdscreen_mono : &vga_stdscreen;
495 #if 0
496 callout_init(&vc->vc_switch_callout);
497 #endif
498
499 vc->vc_fonts[0] = &vga_builtinfont;
500 for (i = 1; i < 8; i++)
501 vc->vc_fonts[i] = 0;
502
503 vc->currentfontset1 = vc->currentfontset2 = 0;
504 }
505
506 void
507 vga_common_attach(self, iot, memt, type)
508 struct device *self;
509 bus_space_tag_t iot, memt;
510 int type;
511 {
512 vga_extended_attach(self, iot, memt, type, NULL);
513 }
514
515 void
516 vga_extended_attach(self, iot, memt, type, map)
517 struct device *self;
518 bus_space_tag_t iot, memt;
519 int type;
520 paddr_t (*map)(void *, off_t, int);
521 {
522 int console;
523 struct vga_config *vc;
524 struct wsemuldisplaydev_attach_args aa;
525
526 console = vga_is_console(iot, type);
527
528 if (console) {
529 vc = &vga_console_vc;
530 vga_console_attached = 1;
531 } else {
532 vc = malloc(sizeof(struct vga_config), M_DEVBUF, M_NOWAIT);
533 if (vc == NULL)
534 return;
535 bzero(vc, sizeof(struct vga_config));
536 vga_init(vc, iot, memt);
537 }
538
539 vc->vc_softc = self;
540 vc->vc_type = type;
541 vc->vc_mmap = map;
542
543 aa.console = console;
544 aa.scrdata = (vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist);
545 aa.accessops = &vga_accessops;
546 aa.accesscookie = vc;
547 aa.defaultscreens = 0;
548
549 config_found(self, &aa, wsemuldisplaydevprint);
550 }
551
552 int
553 vga_cnattach(iot, memt, type, check)
554 bus_space_tag_t iot, memt;
555 int type, check;
556 {
557 long defattr;
558 const struct wsscreen_descr *scr;
559
560 if (check && !vga_common_probe(iot, memt))
561 return (ENXIO);
562
563
564 vga_init(&vga_console_vc, iot, memt);
565 scr = vga_console_vc.currenttype;
566 vga_init_screen(&vga_console_vc, &vga_console_screen, scr, 1, &defattr);
567
568 vga_console_screen.pcs.active = 1;
569 vga_console_vc.active = &vga_console_screen;
570
571 wsdisplay_cnattach(scr, &vga_console_screen,
572 vga_console_screen.pcs.vc_ccol,
573 vga_console_screen.pcs.vc_crow,
574 defattr);
575
576 vgaconsole = 1;
577 vga_console_type = type;
578 return (0);
579 }
580
581 int
582 vga_is_console(iot, type)
583 bus_space_tag_t iot;
584 int type;
585 {
586 if (vgaconsole &&
587 !vga_console_attached &&
588 iot == vga_console_vc.hdl.vh_iot &&
589 (vga_console_type == -1 || (type == vga_console_type)))
590 return (1);
591 return (0);
592 }
593
594 int
595 vga_ioctl(v, cmd, data, flag, p)
596 void *v;
597 u_long cmd;
598 caddr_t data;
599 int flag;
600 struct proc *p;
601 {
602 struct vga_config *vc = v;
603 #if NVGA_PCI > 0
604 int error;
605
606 if (vc->vc_type == WSDISPLAY_TYPE_PCIVGA &&
607 (error = vga_pci_ioctl(v, cmd, data, flag, p)) != ENOTTY)
608 return (error);
609 #endif
610
611 switch (cmd) {
612 case WSDISPLAYIO_GTYPE:
613 *(int *)data = vc->vc_type;
614
615 break;
616
617 case WSDISPLAYIO_GVIDEO:
618 case WSDISPLAYIO_SVIDEO:
619 break;
620
621 case WSDISPLAYIO_GINFO:
622 case WSDISPLAYIO_GETCMAP:
623 case WSDISPLAYIO_PUTCMAP:
624 case WSDISPLAYIO_GCURPOS:
625 case WSDISPLAYIO_SCURPOS:
626 case WSDISPLAYIO_GCURMAX:
627 case WSDISPLAYIO_GCURSOR:
628 case WSDISPLAYIO_SCURSOR:
629 default:
630
631 return ENOTTY;
632 }
633
634 return (0);
635 }
636
637 paddr_t
638 vga_mmap(v, offset, prot)
639 void *v;
640 off_t offset;
641 int prot;
642 {
643 struct vga_config *vc = v;
644
645 if (vc->vc_mmap != NULL)
646 return (*vc->vc_mmap)(v, offset, prot);
647
648 return -1;
649 }
650
651 int
652 vga_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
653 void *v;
654 const struct wsscreen_descr *type;
655 void **cookiep;
656 int *curxp, *curyp;
657 long *defattrp;
658 {
659 struct vga_config *vc = v;
660 struct vgascreen *scr;
661
662 if (vc->nscreens == 1) {
663
664
665
666
667
668 LIST_FIRST(&vc->screens)->pcs.mem =
669 malloc(type->ncols * type->nrows * 2, M_DEVBUF, M_WAITOK);
670 }
671
672 scr = malloc(sizeof(struct vgascreen), M_DEVBUF, M_WAITOK);
673 vga_init_screen(vc, scr, type, vc->nscreens == 0, defattrp);
674
675 if (vc->nscreens == 1) {
676 scr->pcs.active = 1;
677 vc->active = scr;
678 vc->currenttype = type;
679 } else {
680 scr->pcs.mem = malloc(type->ncols * type->nrows * 2,
681 M_DEVBUF, M_WAITOK);
682 pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp);
683 }
684
685 *cookiep = scr;
686 *curxp = scr->pcs.vc_ccol;
687 *curyp = scr->pcs.vc_crow;
688
689 return (0);
690 }
691
692 void
693 vga_free_screen(v, cookie)
694 void *v;
695 void *cookie;
696 {
697 struct vgascreen *vs = cookie;
698 struct vga_config *vc = vs->cfg;
699
700 LIST_REMOVE(vs, next);
701 vc->nscreens--;
702 if (vs != &vga_console_screen) {
703
704
705
706
707 if (vc->nscreens == 1)
708 free(LIST_FIRST(&vc->screens)->pcs.mem, M_DEVBUF);
709
710
711 if (vc->nscreens != 0)
712 free(vs->pcs.mem, M_DEVBUF);
713
714 free(vs, M_DEVBUF);
715 } else
716 panic("vga_free_screen: console");
717
718 if (vc->active == vs)
719 vc->active = NULL;
720 }
721
722 void
723 vga_setfont(vc, scr)
724 struct vga_config *vc;
725 struct vgascreen *scr;
726 {
727 int fontslot1, fontslot2;
728
729 fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0);
730 fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1);
731 if (vc->currentfontset1 != fontslot1 ||
732 vc->currentfontset2 != fontslot2) {
733 vga_setfontset(&vc->hdl, fontslot1, fontslot2);
734 vc->currentfontset1 = fontslot1;
735 vc->currentfontset2 = fontslot2;
736 }
737 }
738
739 int
740 vga_show_screen(v, cookie, waitok, cb, cbarg)
741 void *v;
742 void *cookie;
743 int waitok;
744 void (*cb)(void *, int, int);
745 void *cbarg;
746 {
747 struct vgascreen *scr = cookie, *oldscr;
748 struct vga_config *vc = scr->cfg;
749
750 oldscr = vc->active;
751 if (scr == oldscr) {
752 return (0);
753 }
754
755 vc->wantedscreen = cookie;
756 vc->switchcb = cb;
757 vc->switchcbarg = cbarg;
758 if (cb) {
759 timeout_set(&vc->vc_switch_timeout,
760 (void(*)(void *))vga_doswitch, vc);
761 timeout_add(&vc->vc_switch_timeout, 0);
762 return (EAGAIN);
763 }
764
765 vga_doswitch(vc);
766 return (0);
767 }
768
769 void
770 vga_doswitch(vc)
771 struct vga_config *vc;
772 {
773 struct vgascreen *scr, *oldscr;
774 struct vga_handle *vh = &vc->hdl;
775 const struct wsscreen_descr *type;
776
777 scr = vc->wantedscreen;
778 if (!scr) {
779 printf("vga_doswitch: disappeared\n");
780 (*vc->switchcb)(vc->switchcbarg, EIO, 0);
781 return;
782 }
783 type = scr->pcs.type;
784 oldscr = vc->active;
785 #ifdef DIAGNOSTIC
786 if (oldscr) {
787 if (!oldscr->pcs.active)
788 panic("vga_show_screen: not active");
789 if (oldscr->pcs.type != vc->currenttype)
790 panic("vga_show_screen: bad type");
791 }
792 #endif
793 if (scr == oldscr) {
794 return;
795 }
796 #ifdef DIAGNOSTIC
797 if (scr->pcs.active)
798 panic("vga_show_screen: active");
799 #endif
800
801 scr->vga_rollover = 0;
802
803 if (oldscr) {
804 const struct wsscreen_descr *oldtype = oldscr->pcs.type;
805
806 oldscr->pcs.active = 0;
807 bus_space_read_region_2(vh->vh_memt, vh->vh_memh,
808 oldscr->pcs.dispoffset, oldscr->pcs.mem,
809 oldtype->ncols * oldtype->nrows);
810 }
811
812 if (vc->currenttype != type) {
813 vga_setscreentype(vh, type);
814 vc->currenttype = type;
815 }
816
817 vga_setfont(vc, scr);
818
819
820 scr->pcs.visibleoffset = scr->pcs.dispoffset = scr->mindispoffset;
821 if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) {
822 vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9);
823 vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1);
824 }
825
826 bus_space_write_region_2(vh->vh_memt, vh->vh_memh,
827 scr->pcs.dispoffset, scr->pcs.mem,
828 type->ncols * type->nrows);
829 scr->pcs.active = 1;
830
831 vc->active = scr;
832
833 pcdisplay_cursor_reset(&scr->pcs);
834 pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron,
835 scr->pcs.vc_crow, scr->pcs.vc_ccol);
836
837 vc->wantedscreen = 0;
838 if (vc->switchcb)
839 (*vc->switchcb)(vc->switchcbarg, 0, 0);
840 }
841
842 int
843 vga_load_font(v, cookie, data)
844 void *v;
845 void *cookie;
846 struct wsdisplay_font *data;
847 {
848 struct vga_config *vc = v;
849 struct vgascreen *scr = cookie;
850 char *name2;
851 int res, slot;
852 struct vgafont *f;
853
854 if (scr) {
855 if ((name2 = data->name) != NULL) {
856 while (*name2 && *name2 != ',')
857 name2++;
858 if (*name2)
859 *name2++ = '\0';
860 }
861 res = vga_selectfont(vc, scr, data->name, name2);
862 if (!res)
863 vga_setfont(vc, scr);
864 return (res);
865 }
866
867 if (data->fontwidth != 8 || data->stride != 1)
868 return (EINVAL);
869 if (data->firstchar != 0 || data->numchars != 256)
870 return (EINVAL);
871 #ifndef WSCONS_SUPPORT_PCVTFONTS
872 if (data->encoding == WSDISPLAY_FONTENC_PCVT) {
873 printf("vga: pcvt font support not built in, see vga(4)\n");
874 return (EINVAL);
875 }
876 #endif
877
878 if (data->index < 0) {
879 for (slot = 0; slot < 8; slot++)
880 if (!vc->vc_fonts[slot])
881 break;
882 } else
883 slot = data->index;
884
885 if (slot >= 8)
886 return (ENOSPC);
887
888 if (vc->vc_fonts[slot] != NULL)
889 return (EEXIST);
890 f = malloc(sizeof(struct vgafont), M_DEVBUF, M_WAITOK);
891 if (f == NULL)
892 return (ENOMEM);
893 strlcpy(f->name, data->name, sizeof(f->name));
894 f->height = data->fontheight;
895 f->encoding = data->encoding;
896 #ifdef notyet
897 f->firstchar = data->firstchar;
898 f->numchars = data->numchars;
899 #endif
900 #ifdef VGAFONTDEBUG
901 printf("vga: load %s (8x%d, enc %d) font to slot %d\n", f->name,
902 f->height, f->encoding, slot);
903 #endif
904 vga_loadchars(&vc->hdl, slot, 0, 256, f->height, data->data);
905 f->slot = slot;
906 vc->vc_fonts[slot] = f;
907 data->cookie = f;
908 data->index = slot;
909
910 return (0);
911 }
912
913 void
914 vga_scrollback(v, cookie, lines)
915 void *v;
916 void *cookie;
917 int lines;
918 {
919 struct vga_config *vc = v;
920 struct vgascreen *scr = cookie;
921 struct vga_handle *vh = &vc->hdl;
922
923 if (lines == 0) {
924 if (scr->pcs.visibleoffset == scr->pcs.dispoffset)
925 return;
926
927 scr->pcs.visibleoffset = scr->pcs.dispoffset;
928 }
929 else {
930 int vga_scr_end;
931 int margin = scr->pcs.type->ncols * 2;
932 int ul, we, p, st;
933
934 vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols *
935 scr->pcs.type->nrows * 2);
936 if (scr->vga_rollover > vga_scr_end + margin) {
937 ul = vga_scr_end;
938 we = scr->vga_rollover + scr->pcs.type->ncols * 2;
939 } else {
940 ul = 0;
941 we = 0x8000;
942 }
943 p = (scr->pcs.visibleoffset - ul + we) % we + lines *
944 (scr->pcs.type->ncols * 2);
945 st = (scr->pcs.dispoffset - ul + we) % we;
946 if (p < margin)
947 p = 0;
948 if (p > st - margin)
949 p = st;
950 scr->pcs.visibleoffset = (p + ul) % we;
951 }
952
953
954 vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9);
955 vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1);
956 }
957
958 int
959 vga_alloc_attr(id, fg, bg, flags, attrp)
960 void *id;
961 int fg, bg;
962 int flags;
963 long *attrp;
964 {
965 struct vgascreen *scr = id;
966 struct vga_config *vc = scr->cfg;
967
968 if (vc->hdl.vh_mono) {
969 if (flags & WSATTR_WSCOLORS)
970 return (EINVAL);
971 if (flags & WSATTR_REVERSE)
972 *attrp = 0x70;
973 else
974 *attrp = 0x07;
975 if (flags & WSATTR_UNDERLINE)
976 *attrp |= FG_UNDERLINE;
977 if (flags & WSATTR_HILIT)
978 *attrp |= FG_INTENSE;
979 } else {
980 if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE))
981 return (EINVAL);
982 if (flags & WSATTR_WSCOLORS)
983 *attrp = fgansitopc[fg & 7] | bgansitopc[bg & 7];
984 else
985 *attrp = 7;
986 if ((flags & WSATTR_HILIT) || (fg & 8) || (bg & 8))
987 *attrp += 8;
988 }
989 if (flags & WSATTR_BLINK)
990 *attrp |= FG_BLINK;
991 return (0);
992 }
993
994 void
995 vga_unpack_attr(id, attr, fg, bg, ul)
996 void *id;
997 long attr;
998 int *fg, *bg, *ul;
999 {
1000 struct vgascreen *scr = id;
1001 struct vga_config *vc = scr->cfg;
1002
1003 if (vc->hdl.vh_mono) {
1004 *fg = (attr & 0x07) == 0x07 ? WSCOL_WHITE : WSCOL_BLACK;
1005 *bg = attr & 0x70 ? WSCOL_WHITE : WSCOL_BLACK;
1006 if (ul != NULL)
1007 *ul = *fg != WSCOL_WHITE && (attr & 0x01) ? 1 : 0;
1008 } else {
1009 *fg = pctoansi[attr & 0x07];
1010 *bg = pctoansi[(attr & 0x70) >> 4];
1011 if (ul != NULL)
1012 *ul = 0;
1013 }
1014 if (attr & FG_INTENSE)
1015 *fg += 8;
1016 }
1017
1018 void
1019 vga_copyrows(id, srcrow, dstrow, nrows)
1020 void *id;
1021 int srcrow, dstrow, nrows;
1022 {
1023 struct vgascreen *scr = id;
1024 bus_space_tag_t memt = scr->pcs.hdl->ph_memt;
1025 bus_space_handle_t memh = scr->pcs.hdl->ph_memh;
1026 int ncols = scr->pcs.type->ncols;
1027 bus_size_t srcoff, dstoff;
1028
1029 srcoff = srcrow * ncols + 0;
1030 dstoff = dstrow * ncols + 0;
1031
1032 if (scr->pcs.active) {
1033 if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) {
1034 #ifdef PCDISPLAY_SOFTCURSOR
1035 int cursoron = scr->pcs.cursoron;
1036
1037 if (cursoron)
1038 pcdisplay_cursor(&scr->pcs, 0,
1039 scr->pcs.vc_crow, scr->pcs.vc_ccol);
1040 #endif
1041
1042 if ((scr->pcs.dispoffset + srcrow * ncols * 2)
1043 <= scr->maxdispoffset) {
1044 scr->pcs.dispoffset += srcrow * ncols * 2;
1045 } else {
1046 bus_space_copy_2(memt, memh,
1047 scr->pcs.dispoffset + srcoff * 2,
1048 memh, scr->mindispoffset,
1049 nrows * ncols);
1050 scr->vga_rollover = scr->pcs.dispoffset;
1051 scr->pcs.dispoffset = scr->mindispoffset;
1052 }
1053 scr->pcs.visibleoffset = scr->pcs.dispoffset;
1054 vga_6845_write(&scr->cfg->hdl, startadrh,
1055 scr->pcs.dispoffset >> 9);
1056 vga_6845_write(&scr->cfg->hdl, startadrl,
1057 scr->pcs.dispoffset >> 1);
1058 #ifdef PCDISPLAY_SOFTCURSOR
1059 if (cursoron)
1060 pcdisplay_cursor(&scr->pcs, 1,
1061 scr->pcs.vc_crow, scr->pcs.vc_ccol);
1062 #endif
1063 } else {
1064 bus_space_copy_2(memt, memh,
1065 scr->pcs.dispoffset + srcoff * 2,
1066 memh, scr->pcs.dispoffset + dstoff * 2,
1067 nrows * ncols);
1068 }
1069 } else
1070 bcopy(&scr->pcs.mem[srcoff], &scr->pcs.mem[dstoff],
1071 nrows * ncols * 2);
1072 }
1073
1074 #ifdef WSCONS_SUPPORT_PCVTFONTS
1075
1076 #define NOTYET 0xffff
1077 static u_int16_t pcvt_unichars[0xa0] = {
1078 _e006U,
1079 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1080 NOTYET,
1081 0x2409,
1082 0x240a,
1083 0x240b,
1084 0x240c,
1085 0x240d,
1086 NOTYET, NOTYET,
1087 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1088 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1089 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1090 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1091 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1092 NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1093 0x03c1,
1094 0x03c8,
1095 0x2202,
1096 0x03bb,
1097 0x03b9,
1098 0x03b7,
1099 0x03b5,
1100 0x03c7,
1101 0x2228,
1102 0x2227,
1103 0x222a,
1104 0x2283,
1105 0x2282,
1106 0x03a5,
1107 0x039e,
1108 0x03a8,
1109 0x03a0,
1110 0x21d2,
1111 0x21d4,
1112 0x039b,
1113 0x0398,
1114 0x2243,
1115 0x2207,
1116 0x2206,
1117 0x221d,
1118 0x2234,
1119 0x222b,
1120 0x2215,
1121 0x2216,
1122 _e00eU,
1123 _e00dU,
1124 _e00bU,
1125 _e00cU,
1126 _e007U,
1127 _e008U,
1128 _e009U,
1129 _e00aU,
1130 0x221a,
1131 0x03c9,
1132 0x00a5,
1133 0x03be,
1134 0x00fd,
1135 0x00fe,
1136 0x00f0,
1137 0x00de,
1138 0x00dd,
1139 0x00d7,
1140 0x00d0,
1141 0x00be,
1142 0x00b8,
1143 0x00b4,
1144 0x00af,
1145 0x00ae,
1146 0x00ad,
1147 0x00ac,
1148 0x00a8,
1149 0x2260,
1150 _e005U,
1151 _e004U,
1152 _e003U,
1153 _e002U,
1154 _e001U,
1155 0x03c5,
1156 0x00f8,
1157 0x0153,
1158 0x00f5,
1159 0x00e3,
1160 0x0178,
1161 0x00db,
1162 0x00da,
1163 0x00d9,
1164 0x00d8,
1165 0x0152,
1166 0x00d5,
1167 0x00d4,
1168 0x00d3,
1169 0x00d2,
1170 0x00cf,
1171 0x00ce,
1172 0x00cd,
1173 0x00cc,
1174 0x00cb,
1175 0x00ca,
1176 0x00c8,
1177 0x00c3,
1178 0x00c2,
1179 0x00c1,
1180 0x00c0,
1181 0x00b9,
1182 0x00b7,
1183 0x03b6,
1184 0x00b3,
1185 0x00a9,
1186 0x00a4,
1187 0x03ba,
1188 _e000U
1189 };
1190
1191 int vga_pcvt_mapchar(int, unsigned int *);
1192
1193 int
1194 vga_pcvt_mapchar(uni, index)
1195 int uni;
1196 unsigned int *index;
1197 {
1198 int i;
1199
1200 for (i = 0; i < 0xa0; i++)
1201 if (uni == pcvt_unichars[i]) {
1202 *index = i;
1203 return (5);
1204 }
1205 *index = 0x99;
1206 return (0);
1207 }
1208
1209 #endif
1210
1211 int _vga_mapchar(void *, struct vgafont *, int, unsigned int *);
1212
1213 int
1214 _vga_mapchar(id, font, uni, index)
1215 void *id;
1216 struct vgafont *font;
1217 int uni;
1218 unsigned int *index;
1219 {
1220
1221 switch (font->encoding) {
1222 case WSDISPLAY_FONTENC_ISO:
1223 if (uni < 256) {
1224 *index = uni;
1225 return (5);
1226 } else {
1227 *index = ' ';
1228 return (0);
1229 }
1230 break;
1231 case WSDISPLAY_FONTENC_IBM:
1232 return (pcdisplay_mapchar(id, uni, index));
1233 #ifdef WSCONS_SUPPORT_PCVTFONTS
1234 case WSDISPLAY_FONTENC_PCVT:
1235 return (vga_pcvt_mapchar(uni, index));
1236 #endif
1237 default:
1238 #ifdef VGAFONTDEBUG
1239 printf("_vga_mapchar: encoding=%d\n", font->encoding);
1240 #endif
1241 *index = ' ';
1242 return (0);
1243 }
1244 }
1245
1246 int
1247 vga_mapchar(id, uni, index)
1248 void *id;
1249 int uni;
1250 unsigned int *index;
1251 {
1252 struct vgascreen *scr = id;
1253 unsigned int idx1, idx2;
1254 int res1, res2;
1255
1256 res1 = 0;
1257 idx1 = ' ';
1258 if (scr->fontset1)
1259 res1 = _vga_mapchar(id, scr->fontset1, uni, &idx1);
1260 res2 = -1;
1261 if (scr->fontset2) {
1262 KASSERT(VGA_SCREEN_CANTWOFONTS(scr->pcs.type));
1263 res2 = _vga_mapchar(id, scr->fontset2, uni, &idx2);
1264 }
1265 if (res2 >= res1) {
1266 *index = idx2 | 0x0800;
1267 return (res2);
1268 }
1269 *index = idx1;
1270 return (res1);
1271 }
1272
1273 void
1274 vga_putchar(c, row, col, uc, attr)
1275 void *c;
1276 int row;
1277 int col;
1278 u_int uc;
1279 long attr;
1280 {
1281 struct vgascreen *scr = c;
1282
1283 if (scr->pcs.visibleoffset != scr->pcs.dispoffset)
1284 vga_scrollback(scr->cfg, scr, 0);
1285
1286 pcdisplay_putchar(c, row, col, uc, attr);
1287 }
1288
1289 void
1290 vga_burner(v, on, flags)
1291 void *v;
1292 u_int on, flags;
1293 {
1294 struct vga_config *vc = v;
1295 struct vga_handle *vh = &vc->hdl;
1296 u_int8_t r;
1297 int s;
1298
1299 s = splhigh();
1300 vga_ts_write(vh, syncreset, 0x01);
1301 if (on) {
1302 vga_ts_write(vh, mode, (vga_ts_read(vh, mode) & ~0x20));
1303 r = vga_6845_read(vh, mode) | 0x80;
1304 DELAY(10000);
1305 vga_6845_write(vh, mode, r);
1306 } else {
1307 vga_ts_write(vh, mode, (vga_ts_read(vh, mode) | 0x20));
1308 if (flags & WSDISPLAY_BURN_VBLANK) {
1309 r = vga_6845_read(vh, mode) & ~0x80;
1310 DELAY(10000);
1311 vga_6845_write(vh, mode, r);
1312 }
1313 }
1314 vga_ts_write(vh, syncreset, 0x03);
1315 splx(s);
1316 }
1317
1318 int
1319 vga_getchar(c, row, col, cell)
1320 void *c;
1321 int row, col;
1322 struct wsdisplay_charcell *cell;
1323 {
1324 struct vga_config *vc = c;
1325
1326 return (pcdisplay_getchar(vc->active, row, col, cell));
1327 }
1328
1329 struct cfdriver vga_cd = {
1330 NULL, "vga", DV_DULL
1331 };