File: | dev/ic/vga.c |
Warning: | line 1145, column 17 The left operand of '|' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: vga.c,v 1.74 2021/05/27 23:24:40 cheloha Exp $ */ | |||
2 | /* $NetBSD: vga.c,v 1.28.2.1 2000/06/30 16:27:47 simonb Exp $ */ | |||
3 | ||||
4 | /*- | |||
5 | * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> | |||
6 | * Copyright (c) 1992-1998 Søren Schmidt | |||
7 | * All rights reserved. | |||
8 | * | |||
9 | * Redistribution and use in source and binary forms, with or without | |||
10 | * modification, are permitted provided that the following conditions | |||
11 | * are met: | |||
12 | * 1. Redistributions of source code must retain the above copyright | |||
13 | * notice, this list of conditions and the following disclaimer as | |||
14 | * the first lines of this file unmodified. | |||
15 | * 2. Redistributions in binary form must reproduce the above copyright | |||
16 | * notice, this list of conditions and the following disclaimer in the | |||
17 | * documentation and/or other materials provided with the distribution. | |||
18 | * 3. The name of the author may not be used to endorse or promote products | |||
19 | * derived from this software without specific prior written permission. | |||
20 | * | |||
21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR | |||
22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
24 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
31 | * | |||
32 | */ | |||
33 | /* | |||
34 | * Copyright (c) 1995, 1996 Carnegie-Mellon University. | |||
35 | * All rights reserved. | |||
36 | * | |||
37 | * Author: Chris G. Demetriou | |||
38 | * | |||
39 | * Permission to use, copy, modify and distribute this software and | |||
40 | * its documentation is hereby granted, provided that both the copyright | |||
41 | * notice and this permission notice appear in all copies of the | |||
42 | * software, derivative works or modified versions, and any portions | |||
43 | * thereof, and that both notices appear in supporting documentation. | |||
44 | * | |||
45 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |||
46 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND | |||
47 | * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |||
48 | * | |||
49 | * Carnegie Mellon requests users of this software to return to | |||
50 | * | |||
51 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |||
52 | * School of Computer Science | |||
53 | * Carnegie Mellon University | |||
54 | * Pittsburgh PA 15213-3890 | |||
55 | * | |||
56 | * any improvements or extensions that they make and grant Carnegie the | |||
57 | * rights to redistribute these changes. | |||
58 | */ | |||
59 | ||||
60 | #include "vga.h" | |||
61 | ||||
62 | #include <sys/param.h> | |||
63 | #include <sys/systm.h> | |||
64 | #include <sys/kernel.h> | |||
65 | #include <sys/device.h> | |||
66 | #include <sys/malloc.h> | |||
67 | #include <sys/queue.h> | |||
68 | #include <machine/bus.h> | |||
69 | ||||
70 | #include <dev/ic/mc6845reg.h> | |||
71 | #include <dev/ic/pcdisplayvar.h> | |||
72 | #include <dev/ic/vgareg.h> | |||
73 | ||||
74 | #include <dev/wscons/wsdisplayvar.h> | |||
75 | #include <dev/wscons/wsconsio.h> | |||
76 | #include <dev/wscons/unicode.h> | |||
77 | ||||
78 | #include <dev/ic/vgavar.h> | |||
79 | #include <dev/ic/pcdisplay.h> | |||
80 | ||||
81 | static struct vgafont { | |||
82 | char name[WSFONT_NAME_SIZE32]; | |||
83 | int height; | |||
84 | int encoding; | |||
85 | #ifdef notyet | |||
86 | int firstchar, numchars; | |||
87 | #endif | |||
88 | int slot; | |||
89 | void *fontdata; | |||
90 | } vga_builtinfont = { | |||
91 | .name = "builtin", | |||
92 | .height = 16, | |||
93 | .encoding = WSDISPLAY_FONTENC_IBM1, | |||
94 | #ifdef notyet | |||
95 | .firstchar = 0, | |||
96 | .numchars = 256, | |||
97 | #endif | |||
98 | .slot = 0, | |||
99 | .fontdata = NULL((void *)0) | |||
100 | }; | |||
101 | ||||
102 | int vgaconsole, vga_console_type, vga_console_attached; | |||
103 | struct vgascreen vga_console_screen; | |||
104 | struct vga_config vga_console_vc; | |||
105 | ||||
106 | int vga_selectfont(struct vga_config *, struct vgascreen *, | |||
107 | const char *, const char *); | |||
108 | void vga_init_screen(struct vga_config *, struct vgascreen *, | |||
109 | const struct wsscreen_descr *, int, uint32_t *); | |||
110 | void vga_init(struct vga_config *, bus_space_tag_t, bus_space_tag_t); | |||
111 | void vga_setfont(struct vga_config *, struct vgascreen *); | |||
112 | void vga_pick_monitor_type(struct vga_config *); | |||
113 | ||||
114 | int vga_mapchar(void *, int, unsigned int *); | |||
115 | int vga_putchar(void *, int, int, u_int, uint32_t); | |||
116 | int vga_pack_attr(void *, int, int, int, uint32_t *); | |||
117 | int vga_copyrows(void *, int, int, int); | |||
118 | void vga_unpack_attr(void *, uint32_t, int *, int *, int *); | |||
119 | ||||
120 | static const struct wsdisplay_emulops vga_emulops = { | |||
121 | pcdisplay_cursor, | |||
122 | vga_mapchar, | |||
123 | vga_putchar, | |||
124 | pcdisplay_copycols, | |||
125 | pcdisplay_erasecols, | |||
126 | vga_copyrows, | |||
127 | pcdisplay_eraserows, | |||
128 | vga_pack_attr, | |||
129 | vga_unpack_attr | |||
130 | }; | |||
131 | ||||
132 | /* | |||
133 | * translate WS(=ANSI) color codes to standard pc ones | |||
134 | */ | |||
135 | static const unsigned char fgansitopc[] = { | |||
136 | #ifdef __alpha__ | |||
137 | /* | |||
138 | * XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!! | |||
139 | * XXX We should probably not bother with this | |||
140 | * XXX (reinitialize the palette registers). | |||
141 | */ | |||
142 | FG_BLACK0, FG_BLUE1, FG_GREEN2, FG_CYAN3, FG_RED4, | |||
143 | FG_MAGENTA5, FG_BROWN6, FG_LIGHTGREY7 | |||
144 | #else | |||
145 | FG_BLACK0, FG_RED4, FG_GREEN2, FG_BROWN6, FG_BLUE1, | |||
146 | FG_MAGENTA5, FG_CYAN3, FG_LIGHTGREY7 | |||
147 | #endif | |||
148 | }, bgansitopc[] = { | |||
149 | #ifdef __alpha__ | |||
150 | BG_BLACK0x00, BG_BLUE0x10, BG_GREEN0x20, BG_CYAN0x30, BG_RED0x40, | |||
151 | BG_MAGENTA0x50, BG_BROWN0x60, BG_LIGHTGREY0x70 | |||
152 | #else | |||
153 | BG_BLACK0x00, BG_RED0x40, BG_GREEN0x20, BG_BROWN0x60, BG_BLUE0x10, | |||
154 | BG_MAGENTA0x50, BG_CYAN0x30, BG_LIGHTGREY0x70 | |||
155 | #endif | |||
156 | }; | |||
157 | ||||
158 | /* | |||
159 | * translate standard pc color codes to WS(=ANSI) ones | |||
160 | */ | |||
161 | static const u_int8_t pctoansi[] = { | |||
162 | #ifdef __alpha__ | |||
163 | WSCOL_BLACK0, WSCOL_RED1, WSCOL_GREEN2, WSCOL_BROWN3, | |||
164 | WSCOL_BLUE4, WSCOL_MAGENTA5, WSCOL_CYAN6, WSCOL_WHITE7 | |||
165 | #else | |||
166 | WSCOL_BLACK0, WSCOL_BLUE4, WSCOL_GREEN2, WSCOL_CYAN6, | |||
167 | WSCOL_RED1, WSCOL_MAGENTA5, WSCOL_BROWN3, WSCOL_WHITE7 | |||
168 | #endif | |||
169 | }; | |||
170 | ||||
171 | ||||
172 | const struct wsscreen_descr vga_stdscreen = { | |||
173 | "80x25", 80, 25, | |||
174 | &vga_emulops, | |||
175 | 8, 16, | |||
176 | WSSCREEN_WSCOLORS1 | WSSCREEN_HILIT4 | WSSCREEN_BLINK8 | |||
177 | }, vga_stdscreen_mono = { | |||
178 | "80x25", 80, 25, | |||
179 | &vga_emulops, | |||
180 | 8, 16, | |||
181 | WSSCREEN_HILIT4 | WSSCREEN_UNDERLINE16 | WSSCREEN_BLINK8 | WSSCREEN_REVERSE2 | |||
182 | }, vga_stdscreen_bf = { | |||
183 | "80x25bf", 80, 25, | |||
184 | &vga_emulops, | |||
185 | 8, 16, | |||
186 | WSSCREEN_WSCOLORS1 | WSSCREEN_BLINK8 | |||
187 | }, vga_40lscreen = { | |||
188 | "80x40", 80, 40, | |||
189 | &vga_emulops, | |||
190 | 8, 10, | |||
191 | WSSCREEN_WSCOLORS1 | WSSCREEN_HILIT4 | WSSCREEN_BLINK8 | |||
192 | }, vga_40lscreen_mono = { | |||
193 | "80x40", 80, 40, | |||
194 | &vga_emulops, | |||
195 | 8, 10, | |||
196 | WSSCREEN_HILIT4 | WSSCREEN_UNDERLINE16 | WSSCREEN_BLINK8 | WSSCREEN_REVERSE2 | |||
197 | }, vga_40lscreen_bf = { | |||
198 | "80x40bf", 80, 40, | |||
199 | &vga_emulops, | |||
200 | 8, 10, | |||
201 | WSSCREEN_WSCOLORS1 | WSSCREEN_BLINK8 | |||
202 | }, vga_50lscreen = { | |||
203 | "80x50", 80, 50, | |||
204 | &vga_emulops, | |||
205 | 8, 8, | |||
206 | WSSCREEN_WSCOLORS1 | WSSCREEN_HILIT4 | WSSCREEN_BLINK8 | |||
207 | }, vga_50lscreen_mono = { | |||
208 | "80x50", 80, 50, | |||
209 | &vga_emulops, | |||
210 | 8, 8, | |||
211 | WSSCREEN_HILIT4 | WSSCREEN_UNDERLINE16 | WSSCREEN_BLINK8 | WSSCREEN_REVERSE2 | |||
212 | }, vga_50lscreen_bf = { | |||
213 | "80x50bf", 80, 50, | |||
214 | &vga_emulops, | |||
215 | 8, 8, | |||
216 | WSSCREEN_WSCOLORS1 | WSSCREEN_BLINK8 | |||
217 | }; | |||
218 | ||||
219 | #define VGA_SCREEN_CANTWOFONTS(type)(!((type)->capabilities & 4)) (!((type)->capabilities & WSSCREEN_HILIT4)) | |||
220 | ||||
221 | const struct wsscreen_descr *_vga_scrlist[] = { | |||
222 | &vga_stdscreen, | |||
223 | &vga_stdscreen_bf, | |||
224 | &vga_40lscreen, | |||
225 | &vga_40lscreen_bf, | |||
226 | &vga_50lscreen, | |||
227 | &vga_50lscreen_bf, | |||
228 | /* XXX other formats, graphics screen? */ | |||
229 | }, *_vga_scrlist_mono[] = { | |||
230 | &vga_stdscreen_mono, | |||
231 | &vga_40lscreen_mono, | |||
232 | &vga_50lscreen_mono, | |||
233 | /* XXX other formats, graphics screen? */ | |||
234 | }; | |||
235 | ||||
236 | const struct wsscreen_list vga_screenlist = { | |||
237 | sizeof(_vga_scrlist) / sizeof(struct wsscreen_descr *), | |||
238 | _vga_scrlist | |||
239 | }, vga_screenlist_mono = { | |||
240 | sizeof(_vga_scrlist_mono) / sizeof(struct wsscreen_descr *), | |||
241 | _vga_scrlist_mono | |||
242 | }; | |||
243 | ||||
244 | int vga_ioctl(void *, u_long, caddr_t, int, struct proc *); | |||
245 | paddr_t vga_mmap(void *, off_t, int); | |||
246 | int vga_alloc_screen(void *, const struct wsscreen_descr *, | |||
247 | void **, int *, int *, uint32_t *); | |||
248 | void vga_free_screen(void *, void *); | |||
249 | int vga_show_screen(void *, void *, int, | |||
250 | void (*) (void *, int, int), void *); | |||
251 | int vga_load_font(void *, void *, struct wsdisplay_font *); | |||
252 | int vga_list_font(void *, struct wsdisplay_font *); | |||
253 | void vga_scrollback(void *, void *, int); | |||
254 | void vga_burner(void *v, u_int on, u_int flags); | |||
255 | int vga_getchar(void *, int, int, struct wsdisplay_charcell *); | |||
256 | ||||
257 | void vga_doswitch(void *); | |||
258 | ||||
259 | const struct wsdisplay_accessops vga_accessops = { | |||
260 | .ioctl = vga_ioctl, | |||
261 | .mmap = vga_mmap, | |||
262 | .alloc_screen = vga_alloc_screen, | |||
263 | .free_screen = vga_free_screen, | |||
264 | .show_screen = vga_show_screen, | |||
265 | .load_font = vga_load_font, | |||
266 | .list_font = vga_list_font, | |||
267 | .scrollback = vga_scrollback, | |||
268 | .getchar = vga_getchar, | |||
269 | .burn_screen = vga_burner | |||
270 | }; | |||
271 | ||||
272 | /* | |||
273 | * The following functions implement back-end configuration grabbing | |||
274 | * and attachment. | |||
275 | */ | |||
276 | int | |||
277 | vga_common_probe(bus_space_tag_t iot, bus_space_tag_t memt) | |||
278 | { | |||
279 | bus_space_handle_t ioh_vga, ioh_6845, memh; | |||
280 | u_int8_t regval; | |||
281 | u_int16_t vgadata; | |||
282 | int gotio_vga, gotio_6845, gotmem, mono, rv; | |||
283 | int dispoffset; | |||
284 | ||||
285 | gotio_vga = gotio_6845 = gotmem = rv = 0; | |||
286 | ||||
287 | if (bus_space_map(iot, 0x3c0, 0x10, 0, &ioh_vga)) | |||
288 | goto bad; | |||
289 | gotio_vga = 1; | |||
290 | ||||
291 | /* read "misc output register" */ | |||
292 | regval = bus_space_read_1(iot, ioh_vga, 0xc)((iot)->read_1((ioh_vga), (0xc))); | |||
293 | mono = !(regval & 1); | |||
294 | ||||
295 | if (bus_space_map(iot, (mono ? 0x3b0 : 0x3d0), 0x10, 0, &ioh_6845)) | |||
296 | goto bad; | |||
297 | gotio_6845 = 1; | |||
298 | ||||
299 | if (bus_space_map(memt, 0xa0000, 0x20000, 0, &memh)) | |||
300 | goto bad; | |||
301 | gotmem = 1; | |||
302 | ||||
303 | dispoffset = (mono ? 0x10000 : 0x18000); | |||
304 | ||||
305 | vgadata = bus_space_read_2(memt, memh, dispoffset)((memt)->read_2((memh), (dispoffset))); | |||
306 | bus_space_write_2(memt, memh, dispoffset, 0xa55a)((memt)->write_2((memh), (dispoffset), (0xa55a))); | |||
307 | if (bus_space_read_2(memt, memh, dispoffset)((memt)->read_2((memh), (dispoffset))) != 0xa55a) | |||
308 | goto bad; | |||
309 | bus_space_write_2(memt, memh, dispoffset, vgadata)((memt)->write_2((memh), (dispoffset), (vgadata))); | |||
310 | ||||
311 | /* | |||
312 | * check if this is really a VGA | |||
313 | * (try to write "Color Select" register as XFree86 does) | |||
314 | * XXX check before if at least EGA? | |||
315 | */ | |||
316 | /* reset state */ | |||
317 | (void) bus_space_read_1(iot, ioh_6845, 10)((iot)->read_1((ioh_6845), (10))); | |||
318 | bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX,((iot)->write_1((ioh_vga), (0), (20 | 0x20))) | |||
319 | 20 | 0x20)((iot)->write_1((ioh_vga), (0), (20 | 0x20))); /* colselect | enable */ | |||
320 | regval = bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR)((iot)->read_1((ioh_vga), (1))); | |||
321 | /* toggle the implemented bits */ | |||
322 | bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval ^ 0x0f)((iot)->write_1((ioh_vga), (0), (regval ^ 0x0f))); | |||
323 | bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX,((iot)->write_1((ioh_vga), (0), (20 | 0x20))) | |||
324 | 20 | 0x20)((iot)->write_1((ioh_vga), (0), (20 | 0x20))); | |||
325 | /* read back */ | |||
326 | if (bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR)((iot)->read_1((ioh_vga), (1))) != (regval ^ 0x0f)) | |||
327 | goto bad; | |||
328 | /* restore contents */ | |||
329 | bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval)((iot)->write_1((ioh_vga), (0), (regval))); | |||
330 | ||||
331 | rv = 1; | |||
332 | bad: | |||
333 | if (gotio_vga) | |||
334 | bus_space_unmap(iot, ioh_vga, 0x10); | |||
335 | if (gotio_6845) | |||
336 | bus_space_unmap(iot, ioh_6845, 0x10); | |||
337 | if (gotmem) | |||
338 | bus_space_unmap(memt, memh, 0x20000); | |||
339 | ||||
340 | return (rv); | |||
341 | } | |||
342 | ||||
343 | /* | |||
344 | * We want at least ASCII 32..127 be present in the | |||
345 | * first font slot. | |||
346 | */ | |||
347 | int | |||
348 | vga_selectfont(struct vga_config *vc, struct vgascreen *scr, const char *name1, | |||
349 | const char *name2) /* NULL: take first found */ | |||
350 | { | |||
351 | const struct wsscreen_descr *type = scr->pcs.type; | |||
352 | struct vgafont *f1, *f2; | |||
353 | int i; | |||
354 | ||||
355 | f1 = f2 = 0; | |||
356 | ||||
357 | for (i = 0; i < VGA_MAXFONT8; i++) { | |||
358 | struct vgafont *f = vc->vc_fonts[i]; | |||
359 | if (!f || f->height != type->fontheight) | |||
360 | continue; | |||
361 | if (!f1 && (!name1 || !*name1 || | |||
362 | !strncmp(name1, f->name, WSFONT_NAME_SIZE32))) { | |||
363 | f1 = f; | |||
364 | continue; | |||
365 | } | |||
366 | if (!f2 && | |||
367 | VGA_SCREEN_CANTWOFONTS(type)(!((type)->capabilities & 4)) && | |||
368 | (!name2 || !*name2 || | |||
369 | !strncmp(name2, f->name, WSFONT_NAME_SIZE32))) { | |||
370 | f2 = f; | |||
371 | continue; | |||
372 | } | |||
373 | } | |||
374 | ||||
375 | /* | |||
376 | * The request fails if no primary font was found, | |||
377 | * or if a second font was requested but not found. | |||
378 | */ | |||
379 | if (f1 && (!name2 || !*name2 || f2)) { | |||
380 | #ifdef VGAFONTDEBUG | |||
381 | if (scr != &vga_console_screen || vga_console_attached) { | |||
382 | printf("vga (%s): font1=%s (slot %d)", type->name, | |||
383 | f1->name, f1->slot); | |||
384 | if (f2) | |||
385 | printf(", font2=%s (slot %d)", | |||
386 | f2->name, f2->slot); | |||
387 | printf("\n"); | |||
388 | } | |||
389 | #endif | |||
390 | scr->fontset1 = f1; | |||
391 | scr->fontset2 = f2; | |||
392 | return (0); | |||
393 | } | |||
394 | return (ENXIO6); | |||
395 | } | |||
396 | ||||
397 | void | |||
398 | vga_init_screen(struct vga_config *vc, struct vgascreen *scr, | |||
399 | const struct wsscreen_descr *type, int existing, uint32_t *attrp) | |||
400 | { | |||
401 | int cpos; | |||
402 | int res; | |||
403 | ||||
404 | scr->cfg = vc; | |||
405 | scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl; | |||
406 | scr->pcs.type = type; | |||
407 | scr->pcs.active = 0; | |||
408 | scr->mindispoffset = 0; | |||
409 | scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2; | |||
410 | ||||
411 | if (existing) { | |||
412 | cpos = vga_6845_read(&vc->hdl, cursorh)_pcdisplay_6845_read(&(&vc->hdl)->vh_ph, __builtin_offsetof (struct reg_mc6845, cursorh)) << 8; | |||
413 | cpos |= vga_6845_read(&vc->hdl, cursorl)_pcdisplay_6845_read(&(&vc->hdl)->vh_ph, __builtin_offsetof (struct reg_mc6845, cursorl)); | |||
414 | ||||
415 | /* make sure we have a valid cursor position */ | |||
416 | if (cpos < 0 || cpos >= type->nrows * type->ncols) | |||
417 | cpos = 0; | |||
418 | ||||
419 | scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh)_pcdisplay_6845_read(&(&vc->hdl)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrh)) << 9; | |||
420 | scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl)_pcdisplay_6845_read(&(&vc->hdl)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrl)) << 1; | |||
421 | ||||
422 | /* make sure we have a valid memory offset */ | |||
423 | if (scr->pcs.dispoffset < scr->mindispoffset || | |||
424 | scr->pcs.dispoffset > scr->maxdispoffset) | |||
425 | scr->pcs.dispoffset = scr->mindispoffset; | |||
426 | } else { | |||
427 | cpos = 0; | |||
428 | scr->pcs.dispoffset = scr->mindispoffset; | |||
429 | } | |||
430 | scr->pcs.visibleoffset = scr->pcs.dispoffset; | |||
431 | scr->vga_rollover = 0; | |||
432 | ||||
433 | scr->pcs.vc_crow = cpos / type->ncols; | |||
434 | scr->pcs.vc_ccol = cpos % type->ncols; | |||
435 | pcdisplay_cursor_init(&scr->pcs, existing); | |||
436 | ||||
437 | #ifdef __alpha__ | |||
438 | if (!vc->hdl.vh_mono) | |||
439 | /* | |||
440 | * DEC firmware uses a blue background. | |||
441 | */ | |||
442 | res = vga_pack_attr(scr, WSCOL_WHITE7, WSCOL_BLUE4, | |||
443 | WSATTR_WSCOLORS16, attrp); | |||
444 | else | |||
445 | #endif | |||
446 | res = vga_pack_attr(scr, 0, 0, 0, attrp); | |||
447 | #ifdef DIAGNOSTIC1 | |||
448 | if (res) | |||
449 | panic("vga_init_screen: attribute botch"); | |||
450 | #endif | |||
451 | ||||
452 | scr->pcs.mem = NULL((void *)0); | |||
453 | ||||
454 | scr->fontset1 = scr->fontset2 = 0; | |||
455 | if (vga_selectfont(vc, scr, 0, 0)) { | |||
456 | if (scr == &vga_console_screen) | |||
457 | panic("vga_init_screen: no font"); | |||
458 | else | |||
459 | printf("vga_init_screen: no font\n"); | |||
460 | } | |||
461 | ||||
462 | vc->nscreens++; | |||
463 | LIST_INSERT_HEAD(&vc->screens, scr, next)do { if (((scr)->next.le_next = (&vc->screens)-> lh_first) != ((void *)0)) (&vc->screens)->lh_first-> next.le_prev = &(scr)->next.le_next; (&vc->screens )->lh_first = (scr); (scr)->next.le_prev = &(&vc ->screens)->lh_first; } while (0); | |||
464 | } | |||
465 | ||||
466 | void | |||
467 | vga_init(struct vga_config *vc, bus_space_tag_t iot, bus_space_tag_t memt) | |||
468 | { | |||
469 | struct vga_handle *vh = &vc->hdl; | |||
470 | u_int8_t mor; | |||
471 | int i; | |||
472 | ||||
473 | vh->vh_iotvh_ph.ph_iot = iot; | |||
474 | vh->vh_memtvh_ph.ph_memt = memt; | |||
475 | ||||
476 | if (bus_space_map(vh->vh_iotvh_ph.ph_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga)) | |||
477 | panic("vga_common_setup: can't map vga i/o"); | |||
478 | ||||
479 | /* read "misc output register" */ | |||
480 | mor = bus_space_read_1(vh->vh_iot, vh->vh_ioh_vga, 0xc)((vh->vh_ph.ph_iot)->read_1((vh->vh_ioh_vga), (0xc)) ); | |||
481 | vh->vh_mono = !(mor & 1); | |||
482 | ||||
483 | if (bus_space_map(vh->vh_iotvh_ph.ph_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0, | |||
484 | &vh->vh_ioh_6845vh_ph.ph_ioh_6845)) | |||
485 | panic("vga_common_setup: can't map 6845 i/o"); | |||
486 | ||||
487 | if (bus_space_map(vh->vh_memtvh_ph.ph_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh)) | |||
488 | panic("vga_common_setup: can't map mem space"); | |||
489 | ||||
490 | if (bus_space_subregion(vh->vh_memtvh_ph.ph_memt, vh->vh_allmemh, | |||
491 | (vh->vh_mono ? 0x10000 : 0x18000), 0x8000, | |||
492 | &vh->vh_memhvh_ph.ph_memh)) | |||
493 | panic("vga_common_setup: mem subrange failed"); | |||
494 | ||||
495 | #ifdef __alpha__ | |||
496 | vga_pick_monitor_type(vc); | |||
497 | #endif | |||
498 | ||||
499 | vc->nscreens = 0; | |||
500 | LIST_INIT(&vc->screens)do { ((&vc->screens)->lh_first) = ((void *)0); } while (0); | |||
501 | vc->active = NULL((void *)0); | |||
502 | #ifdef __alpha__ | |||
503 | if (vc->custom_list.screens != NULL((void *)0)) | |||
504 | vc->currenttype = vc->custom_list.screens[0]; | |||
505 | else | |||
506 | #endif | |||
507 | vc->currenttype = | |||
508 | vh->vh_mono ? &vga_stdscreen_mono : &vga_stdscreen; | |||
509 | ||||
510 | vc->vc_fonts[0] = &vga_builtinfont; | |||
511 | for (i = 1; i < VGA_MAXFONT8; i++) | |||
512 | vc->vc_fonts[i] = NULL((void *)0); | |||
513 | ||||
514 | vc->currentfontset1 = vc->currentfontset2 = 0; | |||
515 | ||||
516 | vga_save_palette(vc); | |||
517 | } | |||
518 | ||||
519 | struct vga_config * | |||
520 | vga_common_attach(struct device *self, bus_space_tag_t iot, | |||
521 | bus_space_tag_t memt, int type) | |||
522 | { | |||
523 | return vga_extended_attach(self, iot, memt, type, NULL((void *)0)); | |||
524 | } | |||
525 | ||||
526 | struct vga_config * | |||
527 | vga_extended_attach(struct device *self, bus_space_tag_t iot, | |||
528 | bus_space_tag_t memt, int type, paddr_t (*map)(void *, off_t, int)) | |||
529 | { | |||
530 | int console; | |||
531 | struct vga_config *vc; | |||
532 | struct wsemuldisplaydev_attach_args aa; | |||
533 | ||||
534 | console = vga_is_console(iot, type); | |||
535 | if (console) | |||
536 | vga_console_attached = 1; | |||
537 | ||||
538 | if (type == -1) | |||
539 | return NULL((void *)0); | |||
540 | ||||
541 | if (console) { | |||
542 | vc = &vga_console_vc; | |||
543 | } else { | |||
544 | vc = malloc(sizeof(*vc), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); | |||
545 | if (vc == NULL((void *)0)) | |||
546 | return NULL((void *)0); | |||
547 | vga_init(vc, iot, memt); | |||
548 | } | |||
549 | ||||
550 | vc->vc_softc = self; | |||
551 | vc->vc_type = type; | |||
552 | vc->vc_mmap = map; | |||
553 | ||||
554 | aa.console = console; | |||
555 | #ifdef __alpha__ | |||
556 | if (vc->custom_list.screens != NULL((void *)0)) | |||
557 | aa.scrdata = &vc->custom_list; | |||
558 | else | |||
559 | #endif | |||
560 | aa.scrdata = | |||
561 | vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist; | |||
562 | ||||
563 | aa.accessops = &vga_accessops; | |||
564 | aa.accesscookie = vc; | |||
565 | aa.defaultscreens = 0; | |||
566 | ||||
567 | config_found_sm(self, &aa, wsemuldisplaydevprint, | |||
568 | wsemuldisplaydevsubmatch); | |||
569 | ||||
570 | return vc; | |||
571 | } | |||
572 | ||||
573 | int | |||
574 | vga_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check) | |||
575 | { | |||
576 | uint32_t defattr; | |||
577 | const struct wsscreen_descr *scr; | |||
578 | ||||
579 | if (check && !vga_common_probe(iot, memt)) | |||
580 | return (ENXIO6); | |||
581 | ||||
582 | /* set up bus-independent VGA configuration */ | |||
583 | vga_init(&vga_console_vc, iot, memt); | |||
584 | scr = vga_console_vc.currenttype; | |||
585 | vga_init_screen(&vga_console_vc, &vga_console_screen, scr, 1, &defattr); | |||
586 | ||||
587 | vga_console_screen.pcs.active = 1; | |||
588 | vga_console_vc.active = &vga_console_screen; | |||
589 | ||||
590 | wsdisplay_cnattach(scr, &vga_console_screen, | |||
591 | vga_console_screen.pcs.vc_ccol, | |||
592 | vga_console_screen.pcs.vc_crow, | |||
593 | defattr); | |||
594 | ||||
595 | vgaconsole = 1; | |||
596 | vga_console_type = type; | |||
597 | return (0); | |||
598 | } | |||
599 | ||||
600 | int | |||
601 | vga_is_console(bus_space_tag_t iot, int type) | |||
602 | { | |||
603 | if (vgaconsole && | |||
604 | !vga_console_attached && | |||
605 | iot == vga_console_vc.hdl.vh_iotvh_ph.ph_iot && | |||
606 | (vga_console_type == -1 || (type == vga_console_type))) | |||
607 | return (1); | |||
608 | return (0); | |||
609 | } | |||
610 | ||||
611 | int | |||
612 | vga_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) | |||
613 | { | |||
614 | struct vga_config *vc = v; | |||
615 | int mode; | |||
616 | #if NVGA_PCI1 > 0 | |||
617 | int error; | |||
618 | ||||
619 | if (vc->vc_type == WSDISPLAY_TYPE_PCIVGA8 && | |||
620 | (error = vga_pci_ioctl(v, cmd, data, flag, p)) != ENOTTY25) | |||
621 | return (error); | |||
622 | #endif | |||
623 | ||||
624 | switch (cmd) { | |||
625 | case WSDISPLAYIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) << 16) | ((('W')) << 8) | ((64))): | |||
626 | *(int *)data = vc->vc_type; | |||
627 | /* XXX should get detailed hardware information here */ | |||
628 | break; | |||
629 | ||||
630 | case WSDISPLAYIO_SMODE((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) << 16) | ((('W')) << 8) | ((76))): | |||
631 | mode = *(u_int *)data; | |||
632 | if (mode == WSDISPLAYIO_MODE_EMUL0) { | |||
633 | vga_restore_fonts(vc); | |||
634 | vga_restore_palette(vc); | |||
635 | } | |||
636 | break; | |||
637 | ||||
638 | case WSDISPLAYIO_GVIDEO((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) << 16) | ((('W')) << 8) | ((68))): | |||
639 | case WSDISPLAYIO_SVIDEO((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) << 16) | ((('W')) << 8) | ((69))): | |||
640 | break; | |||
641 | ||||
642 | case WSDISPLAYIO_GINFO((unsigned long)0x40000000 | ((sizeof(struct wsdisplay_fbinfo ) & 0x1fff) << 16) | ((('W')) << 8) | ((65))): | |||
643 | case WSDISPLAYIO_GETCMAP((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_cmap) & 0x1fff) << 16) | ((('W')) << 8) | ((66))): | |||
644 | case WSDISPLAYIO_PUTCMAP((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_cmap) & 0x1fff) << 16) | ((('W')) << 8) | ((67))): | |||
645 | case WSDISPLAYIO_GCURPOS((unsigned long)0x40000000 | ((sizeof(struct wsdisplay_curpos ) & 0x1fff) << 16) | ((('W')) << 8) | ((70))): | |||
646 | case WSDISPLAYIO_SCURPOS((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_curpos ) & 0x1fff) << 16) | ((('W')) << 8) | ((71))): | |||
647 | case WSDISPLAYIO_GCURMAX((unsigned long)0x40000000 | ((sizeof(struct wsdisplay_curpos ) & 0x1fff) << 16) | ((('W')) << 8) | ((72))): | |||
648 | case WSDISPLAYIO_GCURSOR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct wsdisplay_cursor) & 0x1fff) << 16) | ((('W' )) << 8) | ((73))): | |||
649 | case WSDISPLAYIO_SCURSOR((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_cursor ) & 0x1fff) << 16) | ((('W')) << 8) | ((74))): | |||
650 | default: | |||
651 | /* NONE of these operations are by the generic VGA driver. */ | |||
652 | return ENOTTY25; | |||
653 | } | |||
654 | ||||
655 | return (0); | |||
656 | } | |||
657 | ||||
658 | paddr_t | |||
659 | vga_mmap(void *v, off_t offset, int prot) | |||
660 | { | |||
661 | struct vga_config *vc = v; | |||
662 | ||||
663 | if (vc->vc_mmap != NULL((void *)0)) | |||
664 | return (*vc->vc_mmap)(v, offset, prot); | |||
665 | ||||
666 | return (paddr_t)-1; | |||
667 | } | |||
668 | ||||
669 | int | |||
670 | vga_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, | |||
671 | int *curxp, int *curyp, uint32_t *defattrp) | |||
672 | { | |||
673 | struct vga_config *vc = v; | |||
674 | struct vgascreen *scr; | |||
675 | ||||
676 | if (vc->nscreens == 1) { | |||
677 | /* | |||
678 | * When allocating the second screen, get backing store | |||
679 | * for the first one too. | |||
680 | * XXX We could be more clever and use video RAM. | |||
681 | */ | |||
682 | scr = LIST_FIRST(&vc->screens)((&vc->screens)->lh_first); | |||
683 | scr->pcs.mem = mallocarray(scr->pcs.type->ncols, | |||
684 | scr->pcs.type->nrows * 2, M_DEVBUF2, M_WAITOK0x0001); | |||
685 | } | |||
686 | ||||
687 | scr = malloc(sizeof(struct vgascreen), M_DEVBUF2, M_WAITOK0x0001); | |||
688 | vga_init_screen(vc, scr, type, vc->nscreens == 0, defattrp); | |||
689 | ||||
690 | if (vc->nscreens == 1) { | |||
691 | scr->pcs.active = 1; | |||
692 | vc->active = scr; | |||
693 | vc->currenttype = type; | |||
694 | } else { | |||
695 | scr->pcs.mem = mallocarray(type->ncols, | |||
696 | type->nrows * 2, M_DEVBUF2, M_WAITOK0x0001); | |||
697 | pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp); | |||
698 | } | |||
699 | ||||
700 | *cookiep = scr; | |||
701 | *curxp = scr->pcs.vc_ccol; | |||
702 | *curyp = scr->pcs.vc_crow; | |||
703 | ||||
704 | return (0); | |||
705 | } | |||
706 | ||||
707 | void | |||
708 | vga_free_screen(void *v, void *cookie) | |||
709 | { | |||
710 | struct vgascreen *vs = cookie; | |||
711 | struct vga_config *vc = vs->cfg; | |||
712 | ||||
713 | LIST_REMOVE(vs, next)do { if ((vs)->next.le_next != ((void *)0)) (vs)->next. le_next->next.le_prev = (vs)->next.le_prev; *(vs)->next .le_prev = (vs)->next.le_next; ((vs)->next.le_prev) = ( (void *)-1); ((vs)->next.le_next) = ((void *)-1); } while ( 0); | |||
714 | vc->nscreens--; | |||
715 | if (vs != &vga_console_screen) { | |||
716 | /* | |||
717 | * deallocating the one but last screen | |||
718 | * removes backing store for the last one | |||
719 | */ | |||
720 | if (vc->nscreens == 1) | |||
721 | free(LIST_FIRST(&vc->screens)((&vc->screens)->lh_first)->pcs.mem, M_DEVBUF2, 0); | |||
722 | ||||
723 | /* Last screen has no backing store */ | |||
724 | if (vc->nscreens != 0) | |||
725 | free(vs->pcs.mem, M_DEVBUF2, 0); | |||
726 | ||||
727 | free(vs, M_DEVBUF2, sizeof *vs); | |||
728 | } else | |||
729 | panic("vga_free_screen: console"); | |||
730 | ||||
731 | if (vc->active == vs) | |||
732 | vc->active = NULL((void *)0); | |||
733 | } | |||
734 | ||||
735 | void | |||
736 | vga_setfont(struct vga_config *vc, struct vgascreen *scr) | |||
737 | { | |||
738 | int fontslot1, fontslot2; | |||
739 | ||||
740 | fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0); | |||
741 | fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1); | |||
742 | if (vc->currentfontset1 != fontslot1 || | |||
743 | vc->currentfontset2 != fontslot2) { | |||
744 | vga_setfontset(&vc->hdl, fontslot1, fontslot2); | |||
745 | vc->currentfontset1 = fontslot1; | |||
746 | vc->currentfontset2 = fontslot2; | |||
747 | } | |||
748 | } | |||
749 | ||||
750 | int | |||
751 | vga_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int), | |||
752 | void *cbarg) | |||
753 | { | |||
754 | struct vgascreen *scr = cookie, *oldscr; | |||
755 | struct vga_config *vc = scr->cfg; | |||
756 | ||||
757 | oldscr = vc->active; /* can be NULL! */ | |||
758 | if (scr == oldscr) { | |||
759 | return (0); | |||
760 | } | |||
761 | ||||
762 | vc->wantedscreen = cookie; | |||
763 | vc->switchcb = cb; | |||
764 | vc->switchcbarg = cbarg; | |||
765 | if (cb) { | |||
766 | timeout_set(&vc->vc_switch_timeout, vga_doswitch, vc); | |||
767 | timeout_add(&vc->vc_switch_timeout, 0); | |||
768 | return (EAGAIN35); | |||
769 | } | |||
770 | ||||
771 | vga_doswitch(vc); | |||
772 | return (0); | |||
773 | } | |||
774 | ||||
775 | void | |||
776 | vga_doswitch(void *arg) | |||
777 | { | |||
778 | struct vga_config *vc = arg; | |||
779 | struct vgascreen *scr, *oldscr; | |||
780 | struct vga_handle *vh = &vc->hdl; | |||
781 | const struct wsscreen_descr *type; | |||
782 | int s; | |||
783 | ||||
784 | scr = vc->wantedscreen; | |||
785 | if (!scr) { | |||
786 | printf("vga_doswitch: disappeared\n"); | |||
787 | (*vc->switchcb)(vc->switchcbarg, EIO5, 0); | |||
788 | return; | |||
789 | } | |||
790 | ||||
791 | type = scr->pcs.type; | |||
792 | oldscr = vc->active; /* can be NULL! */ | |||
793 | if (scr == oldscr) | |||
794 | return; | |||
795 | s = spltty()splraise(0x9); | |||
796 | #ifdef DIAGNOSTIC1 | |||
797 | if (oldscr) { | |||
798 | if (!oldscr->pcs.active) | |||
799 | panic("vga_show_screen: not active"); | |||
800 | if (oldscr->pcs.type != vc->currenttype) | |||
801 | panic("vga_show_screen: bad type"); | |||
802 | } | |||
803 | if (scr->pcs.active) | |||
804 | panic("vga_show_screen: active"); | |||
805 | #endif | |||
806 | ||||
807 | scr->vga_rollover = 0; | |||
808 | ||||
809 | if (oldscr) { | |||
810 | const struct wsscreen_descr *oldtype = oldscr->pcs.type; | |||
811 | ||||
812 | oldscr->pcs.active = 0; | |||
813 | bus_space_read_region_2(vh->vh_memt, vh->vh_memh,((vh->vh_ph.ph_memt)->read_region_2((vh->vh_ph.ph_memh ), (oldscr->pcs.dispoffset), (oldscr->pcs.mem), (oldtype ->ncols * oldtype->nrows))) | |||
814 | oldscr->pcs.dispoffset, oldscr->pcs.mem,((vh->vh_ph.ph_memt)->read_region_2((vh->vh_ph.ph_memh ), (oldscr->pcs.dispoffset), (oldscr->pcs.mem), (oldtype ->ncols * oldtype->nrows))) | |||
815 | oldtype->ncols * oldtype->nrows)((vh->vh_ph.ph_memt)->read_region_2((vh->vh_ph.ph_memh ), (oldscr->pcs.dispoffset), (oldscr->pcs.mem), (oldtype ->ncols * oldtype->nrows))); | |||
816 | } | |||
817 | ||||
818 | if (vc->currenttype != type) { | |||
819 | vga_setscreentype(vh, type); | |||
820 | vc->currenttype = type; | |||
821 | } | |||
822 | ||||
823 | vga_restore_fonts(vc); | |||
824 | vga_setfont(vc, scr); | |||
825 | vga_restore_palette(vc); | |||
826 | ||||
827 | scr->pcs.visibleoffset = scr->pcs.dispoffset = scr->mindispoffset; | |||
828 | if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) { | |||
829 | vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrh), scr->pcs.dispoffset >> 9); | |||
830 | vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrl), scr->pcs.dispoffset >> 1); | |||
831 | } | |||
832 | ||||
833 | bus_space_write_region_2(vh->vh_memt, vh->vh_memh,((vh->vh_ph.ph_memt)->write_region_2((vh->vh_ph.ph_memh ), (scr->pcs.dispoffset), (scr->pcs.mem), (type->ncols * type->nrows))) | |||
834 | scr->pcs.dispoffset, scr->pcs.mem,((vh->vh_ph.ph_memt)->write_region_2((vh->vh_ph.ph_memh ), (scr->pcs.dispoffset), (scr->pcs.mem), (type->ncols * type->nrows))) | |||
835 | type->ncols * type->nrows)((vh->vh_ph.ph_memt)->write_region_2((vh->vh_ph.ph_memh ), (scr->pcs.dispoffset), (scr->pcs.mem), (type->ncols * type->nrows))); | |||
836 | scr->pcs.active = 1; | |||
837 | splx(s)spllower(s); | |||
838 | ||||
839 | vc->active = scr; | |||
840 | ||||
841 | pcdisplay_cursor_reset(&scr->pcs); | |||
842 | pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron, | |||
843 | scr->pcs.vc_crow, scr->pcs.vc_ccol); | |||
844 | ||||
845 | vc->wantedscreen = 0; | |||
846 | if (vc->switchcb) | |||
847 | (*vc->switchcb)(vc->switchcbarg, 0, 0); | |||
848 | } | |||
849 | ||||
850 | int | |||
851 | vga_load_font(void *v, void *cookie, struct wsdisplay_font *data) | |||
852 | { | |||
853 | struct vga_config *vc = v; | |||
854 | struct vgascreen *scr = cookie; | |||
855 | char *name2; | |||
856 | int res, slot; | |||
857 | struct vgafont *f; | |||
858 | ||||
859 | if (data->data == NULL((void *)0)) { | |||
860 | if (scr == NULL((void *)0)) | |||
861 | return EINVAL22; | |||
862 | ||||
863 | if ((name2 = data->name) != NULL((void *)0)) { | |||
864 | while (*name2 && *name2 != ',') | |||
865 | name2++; | |||
866 | if (*name2) | |||
867 | *name2++ = '\0'; | |||
868 | } | |||
869 | res = vga_selectfont(vc, scr, data->name, name2); | |||
870 | if (res == 0) | |||
871 | vga_setfont(vc, scr); | |||
872 | return (res); | |||
873 | } | |||
874 | ||||
875 | if (data->fontwidth != 8 || data->stride != 1) | |||
876 | return (EINVAL22); /* XXX 1 byte per line */ | |||
877 | if (data->firstchar != 0 || data->numchars != 256) | |||
878 | return (EINVAL22); | |||
879 | ||||
880 | if (data->index < 0) { | |||
881 | for (slot = 0; slot < VGA_MAXFONT8; slot++) | |||
882 | if (!vc->vc_fonts[slot]) | |||
883 | break; | |||
884 | } else | |||
885 | slot = data->index; | |||
886 | ||||
887 | if (slot >= VGA_MAXFONT8) | |||
888 | return (ENOSPC28); | |||
889 | ||||
890 | if (vc->vc_fonts[slot] != NULL((void *)0)) | |||
891 | return (EEXIST17); | |||
892 | f = malloc(sizeof(struct vgafont), M_DEVBUF2, M_WAITOK0x0001 | M_CANFAIL0x0004); | |||
893 | if (f == NULL((void *)0)) | |||
894 | return (ENOMEM12); | |||
895 | strlcpy(f->name, data->name, sizeof(f->name)); | |||
896 | f->height = data->fontheight; | |||
897 | f->encoding = data->encoding; | |||
898 | #ifdef notyet | |||
899 | f->firstchar = data->firstchar; | |||
900 | f->numchars = data->numchars; | |||
901 | #endif | |||
902 | #ifdef VGAFONTDEBUG | |||
903 | printf("vga: load %s (8x%d, enc %d) font to slot %d\n", f->name, | |||
904 | f->height, f->encoding, slot); | |||
905 | #endif | |||
906 | vga_loadchars(&vc->hdl, slot, 0, 256, f->height, data->data); | |||
907 | f->slot = slot; | |||
908 | f->fontdata = data->data; | |||
909 | vc->vc_fonts[slot] = f; | |||
910 | data->cookie = f; | |||
911 | data->index = slot; | |||
912 | ||||
913 | return (0); | |||
914 | } | |||
915 | ||||
916 | int | |||
917 | vga_list_font(void *v, struct wsdisplay_font *data) | |||
918 | { | |||
919 | struct vga_config *vc = v; | |||
920 | struct vgafont *f; | |||
921 | ||||
922 | if (data->index < 0 || data->index >= VGA_MAXFONT8) | |||
923 | return EINVAL22; | |||
924 | ||||
925 | if ((f = vc->vc_fonts[data->index]) == NULL((void *)0)) | |||
926 | return EINVAL22; | |||
927 | ||||
928 | strlcpy(data->name, f->name, sizeof data->name); | |||
929 | #ifdef notyet | |||
930 | data->firstchar = f->firstchar; | |||
931 | data->numchars = f->numchars; | |||
932 | #else | |||
933 | data->firstchar = 0; | |||
934 | data->numchars = 256; | |||
935 | #endif | |||
936 | data->encoding = f->encoding; | |||
937 | data->fontwidth = 8; | |||
938 | data->fontheight = f->height; | |||
939 | data->stride = 1; | |||
940 | data->bitorder = data->byteorder = WSDISPLAY_FONTORDER_L2R1; | |||
941 | ||||
942 | return (0); | |||
943 | } | |||
944 | ||||
945 | void | |||
946 | vga_scrollback(void *v, void *cookie, int lines) | |||
947 | { | |||
948 | struct vga_config *vc = v; | |||
949 | struct vgascreen *scr = cookie; | |||
950 | struct vga_handle *vh = &vc->hdl; | |||
951 | ||||
952 | if (lines == 0) { | |||
953 | if (scr->pcs.visibleoffset == scr->pcs.dispoffset) | |||
954 | return; | |||
955 | ||||
956 | scr->pcs.visibleoffset = scr->pcs.dispoffset; /* reset */ | |||
957 | } | |||
958 | else { | |||
959 | int vga_scr_end; | |||
960 | int margin = scr->pcs.type->ncols * 2; | |||
961 | int ul, we, p, st; | |||
962 | ||||
963 | vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols * | |||
964 | scr->pcs.type->nrows * 2); | |||
965 | if (scr->vga_rollover > vga_scr_end + margin) { | |||
966 | ul = vga_scr_end; | |||
967 | we = scr->vga_rollover + scr->pcs.type->ncols * 2; | |||
968 | } else { | |||
969 | ul = 0; | |||
970 | we = 0x8000; | |||
971 | } | |||
972 | p = (scr->pcs.visibleoffset - ul + we) % we + lines * | |||
973 | (scr->pcs.type->ncols * 2); | |||
974 | st = (scr->pcs.dispoffset - ul + we) % we; | |||
975 | if (p < margin) | |||
976 | p = 0; | |||
977 | if (p > st - margin) | |||
978 | p = st; | |||
979 | scr->pcs.visibleoffset = (p + ul) % we; | |||
980 | } | |||
981 | ||||
982 | /* update visible position */ | |||
983 | vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrh), scr->pcs.visibleoffset >> 9); | |||
984 | vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrl), scr->pcs.visibleoffset >> 1); | |||
985 | } | |||
986 | ||||
987 | int | |||
988 | vga_pack_attr(void *id, int fg, int bg, int flags, uint32_t *attrp) | |||
989 | { | |||
990 | struct vgascreen *scr = id; | |||
991 | struct vga_config *vc = scr->cfg; | |||
992 | ||||
993 | if (vc->hdl.vh_mono) { | |||
994 | if (flags & WSATTR_WSCOLORS16) | |||
995 | return (EINVAL22); | |||
996 | if (flags & WSATTR_REVERSE1) | |||
997 | *attrp = 0x70; | |||
998 | else | |||
999 | *attrp = 0x07; | |||
1000 | if (flags & WSATTR_UNDERLINE8) | |||
1001 | *attrp |= FG_UNDERLINE0x01; | |||
1002 | if (flags & WSATTR_HILIT2) | |||
1003 | *attrp |= FG_INTENSE0x08; | |||
1004 | } else { | |||
1005 | if (flags & (WSATTR_UNDERLINE8 | WSATTR_REVERSE1)) | |||
1006 | return (EINVAL22); | |||
1007 | if (flags & WSATTR_WSCOLORS16) | |||
1008 | *attrp = fgansitopc[fg & 7] | bgansitopc[bg & 7]; | |||
1009 | else | |||
1010 | *attrp = 7; | |||
1011 | if ((flags & WSATTR_HILIT2) || (fg & 8) || (bg & 8)) | |||
1012 | *attrp += 8; | |||
1013 | } | |||
1014 | if (flags & WSATTR_BLINK4) | |||
1015 | *attrp |= FG_BLINK0x80; | |||
1016 | return (0); | |||
1017 | } | |||
1018 | ||||
1019 | void | |||
1020 | vga_unpack_attr(void *id, uint32_t attr, int *fg, int *bg, int *ul) | |||
1021 | { | |||
1022 | struct vgascreen *scr = id; | |||
1023 | struct vga_config *vc = scr->cfg; | |||
1024 | ||||
1025 | if (vc->hdl.vh_mono) { | |||
1026 | *fg = (attr & 0x07) == 0x07 ? WSCOL_WHITE7 : WSCOL_BLACK0; | |||
1027 | *bg = attr & 0x70 ? WSCOL_WHITE7 : WSCOL_BLACK0; | |||
1028 | if (ul != NULL((void *)0)) | |||
1029 | *ul = *fg != WSCOL_WHITE7 && (attr & 0x01) ? 1 : 0; | |||
1030 | } else { | |||
1031 | *fg = pctoansi[attr & 0x07]; | |||
1032 | *bg = pctoansi[(attr & 0x70) >> 4]; | |||
1033 | if (ul != NULL((void *)0)) | |||
1034 | *ul = 0; | |||
1035 | } | |||
1036 | if (attr & FG_INTENSE0x08) | |||
1037 | *fg += 8; | |||
1038 | } | |||
1039 | ||||
1040 | int | |||
1041 | vga_copyrows(void *id, int srcrow, int dstrow, int nrows) | |||
1042 | { | |||
1043 | struct vgascreen *scr = id; | |||
1044 | bus_space_tag_t memt = scr->pcs.hdl->ph_memt; | |||
1045 | bus_space_handle_t memh = scr->pcs.hdl->ph_memh; | |||
1046 | int ncols = scr->pcs.type->ncols; | |||
1047 | bus_size_t srcoff, dstoff; | |||
1048 | int s; | |||
1049 | ||||
1050 | srcoff = srcrow * ncols + 0; | |||
1051 | dstoff = dstrow * ncols + 0; | |||
1052 | ||||
1053 | s = spltty()splraise(0x9); | |||
1054 | if (scr->pcs.active) { | |||
1055 | if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) { | |||
1056 | #ifdef PCDISPLAY_SOFTCURSOR | |||
1057 | int cursoron = scr->pcs.cursoron; | |||
1058 | ||||
1059 | /* NOTE this assumes pcdisplay_cursor() never fails */ | |||
1060 | if (cursoron) | |||
1061 | pcdisplay_cursor(&scr->pcs, 0, | |||
1062 | scr->pcs.vc_crow, scr->pcs.vc_ccol); | |||
1063 | #endif | |||
1064 | /* scroll up whole screen */ | |||
1065 | if ((scr->pcs.dispoffset + srcrow * ncols * 2) | |||
1066 | <= scr->maxdispoffset) { | |||
1067 | scr->pcs.dispoffset += srcrow * ncols * 2; | |||
1068 | } else { | |||
1069 | bus_space_copy_2(memt, memh,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->mindispoffset), (nrows * ncols))) | |||
1070 | scr->pcs.dispoffset + srcoff * 2,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->mindispoffset), (nrows * ncols))) | |||
1071 | memh, scr->mindispoffset,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->mindispoffset), (nrows * ncols))) | |||
1072 | nrows * ncols)((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->mindispoffset), (nrows * ncols))); | |||
1073 | scr->vga_rollover = scr->pcs.dispoffset; | |||
1074 | scr->pcs.dispoffset = scr->mindispoffset; | |||
1075 | } | |||
1076 | scr->pcs.visibleoffset = scr->pcs.dispoffset; | |||
1077 | vga_6845_write(&scr->cfg->hdl, startadrh,_pcdisplay_6845_write(&(&scr->cfg->hdl)->vh_ph , __builtin_offsetof(struct reg_mc6845, startadrh), scr->pcs .dispoffset >> 9) | |||
1078 | scr->pcs.dispoffset >> 9)_pcdisplay_6845_write(&(&scr->cfg->hdl)->vh_ph , __builtin_offsetof(struct reg_mc6845, startadrh), scr->pcs .dispoffset >> 9); | |||
1079 | vga_6845_write(&scr->cfg->hdl, startadrl,_pcdisplay_6845_write(&(&scr->cfg->hdl)->vh_ph , __builtin_offsetof(struct reg_mc6845, startadrl), scr->pcs .dispoffset >> 1) | |||
1080 | scr->pcs.dispoffset >> 1)_pcdisplay_6845_write(&(&scr->cfg->hdl)->vh_ph , __builtin_offsetof(struct reg_mc6845, startadrl), scr->pcs .dispoffset >> 1); | |||
1081 | #ifdef PCDISPLAY_SOFTCURSOR | |||
1082 | /* NOTE this assumes pcdisplay_cursor() never fails */ | |||
1083 | if (cursoron) | |||
1084 | pcdisplay_cursor(&scr->pcs, 1, | |||
1085 | scr->pcs.vc_crow, scr->pcs.vc_ccol); | |||
1086 | #endif | |||
1087 | } else { | |||
1088 | bus_space_copy_2(memt, memh,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->pcs.dispoffset + dstoff * 2), (nrows * ncols ))) | |||
1089 | scr->pcs.dispoffset + srcoff * 2,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->pcs.dispoffset + dstoff * 2), (nrows * ncols ))) | |||
1090 | memh, scr->pcs.dispoffset + dstoff * 2,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->pcs.dispoffset + dstoff * 2), (nrows * ncols ))) | |||
1091 | nrows * ncols)((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->pcs.dispoffset + dstoff * 2), (nrows * ncols ))); | |||
1092 | } | |||
1093 | } else | |||
1094 | bcopy(&scr->pcs.mem[srcoff], &scr->pcs.mem[dstoff], | |||
1095 | nrows * ncols * 2); | |||
1096 | splx(s)spllower(s); | |||
1097 | ||||
1098 | return 0; | |||
1099 | } | |||
1100 | ||||
1101 | int _vga_mapchar(void *, struct vgafont *, int, unsigned int *); | |||
1102 | ||||
1103 | int | |||
1104 | _vga_mapchar(void *id, struct vgafont *font, int uni, unsigned int *index) | |||
1105 | { | |||
1106 | ||||
1107 | switch (font->encoding) { | |||
1108 | case WSDISPLAY_FONTENC_ISO0: | |||
1109 | if (uni < 256) { | |||
1110 | *index = uni; | |||
1111 | return (5); | |||
1112 | } else { | |||
1113 | *index = '?'; | |||
1114 | return (0); | |||
1115 | } | |||
1116 | break; | |||
1117 | case WSDISPLAY_FONTENC_IBM1: | |||
1118 | return (pcdisplay_mapchar(id, uni, index)); | |||
1119 | default: | |||
1120 | #ifdef VGAFONTDEBUG | |||
1121 | printf("_vga_mapchar: encoding=%d\n", font->encoding); | |||
1122 | #endif | |||
1123 | *index = '?'; | |||
1124 | return (0); | |||
1125 | } | |||
1126 | } | |||
1127 | ||||
1128 | int | |||
1129 | vga_mapchar(void *id, int uni, unsigned int *index) | |||
1130 | { | |||
1131 | struct vgascreen *scr = id; | |||
1132 | unsigned int idx1, idx2; | |||
| ||||
1133 | int res1, res2; | |||
1134 | ||||
1135 | res1 = 0; | |||
1136 | idx1 = ' '; /* space */ | |||
1137 | if (scr->fontset1) | |||
1138 | res1 = _vga_mapchar(id, scr->fontset1, uni, &idx1); | |||
1139 | res2 = -1; | |||
1140 | if (scr->fontset2) { | |||
1141 | KASSERT(VGA_SCREEN_CANTWOFONTS(scr->pcs.type))(((!((scr->pcs.type)->capabilities & 4))) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/vga.c", 1141, "VGA_SCREEN_CANTWOFONTS(scr->pcs.type)")); | |||
1142 | res2 = _vga_mapchar(id, scr->fontset2, uni, &idx2); | |||
1143 | } | |||
1144 | if (res2 >= res1) { | |||
1145 | *index = idx2 | 0x0800; /* attribute bit 3 */ | |||
| ||||
1146 | return (res2); | |||
1147 | } | |||
1148 | *index = idx1; | |||
1149 | return (res1); | |||
1150 | } | |||
1151 | ||||
1152 | int | |||
1153 | vga_putchar(void *c, int row, int col, u_int uc, uint32_t attr) | |||
1154 | { | |||
1155 | struct vgascreen *scr = c; | |||
1156 | int rc; | |||
1157 | int s; | |||
1158 | ||||
1159 | s = spltty()splraise(0x9); | |||
1160 | if (scr->pcs.active && scr->pcs.visibleoffset != scr->pcs.dispoffset) | |||
1161 | vga_scrollback(scr->cfg, scr, 0); | |||
1162 | rc = pcdisplay_putchar(c, row, col, uc, attr); | |||
1163 | splx(s)spllower(s); | |||
1164 | ||||
1165 | return rc; | |||
1166 | } | |||
1167 | ||||
1168 | void | |||
1169 | vga_burner(void *v, u_int on, u_int flags) | |||
1170 | { | |||
1171 | struct vga_config *vc = v; | |||
1172 | struct vga_handle *vh = &vc->hdl; | |||
1173 | u_int8_t r; | |||
1174 | int s; | |||
1175 | ||||
1176 | s = splhigh()splraise(0xd); | |||
1177 | vga_ts_write(vh, syncreset, 0x01)_vga_ts_write(vh, __builtin_offsetof(struct reg_vgats, syncreset ), 0x01); | |||
1178 | if (on) { | |||
1179 | vga_ts_write(vh, mode, (vga_ts_read(vh, mode) & ~0x20))_vga_ts_write(vh, __builtin_offsetof(struct reg_vgats, mode), (_vga_ts_read(vh, __builtin_offsetof(struct reg_vgats, mode) ) & ~0x20)); | |||
1180 | r = vga_6845_read(vh, mode)_pcdisplay_6845_read(&(vh)->vh_ph, __builtin_offsetof( struct reg_mc6845, mode)) | 0x80; | |||
1181 | DELAY(10000)(*delay_func)(10000); | |||
1182 | vga_6845_write(vh, mode, r)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, mode), r); | |||
1183 | } else { | |||
1184 | vga_ts_write(vh, mode, (vga_ts_read(vh, mode) | 0x20))_vga_ts_write(vh, __builtin_offsetof(struct reg_vgats, mode), (_vga_ts_read(vh, __builtin_offsetof(struct reg_vgats, mode) ) | 0x20)); | |||
1185 | if (flags & WSDISPLAY_BURN_VBLANK0x0001) { | |||
1186 | r = vga_6845_read(vh, mode)_pcdisplay_6845_read(&(vh)->vh_ph, __builtin_offsetof( struct reg_mc6845, mode)) & ~0x80; | |||
1187 | DELAY(10000)(*delay_func)(10000); | |||
1188 | vga_6845_write(vh, mode, r)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, mode), r); | |||
1189 | } | |||
1190 | } | |||
1191 | vga_ts_write(vh, syncreset, 0x03)_vga_ts_write(vh, __builtin_offsetof(struct reg_vgats, syncreset ), 0x03); | |||
1192 | splx(s)spllower(s); | |||
1193 | } | |||
1194 | ||||
1195 | int | |||
1196 | vga_getchar(void *c, int row, int col, struct wsdisplay_charcell *cell) | |||
1197 | { | |||
1198 | struct vga_config *vc = c; | |||
1199 | ||||
1200 | return (pcdisplay_getchar(vc->active, row, col, cell)); | |||
1201 | } | |||
1202 | ||||
1203 | void | |||
1204 | vga_save_palette(struct vga_config *vc) | |||
1205 | { | |||
1206 | struct vga_handle *vh = &vc->hdl; | |||
1207 | uint i; | |||
1208 | uint8_t *palette = vc->vc_palette; | |||
1209 | ||||
1210 | if (vh->vh_mono) | |||
1211 | return; | |||
1212 | ||||
1213 | vga_raw_write(vh, VGA_DAC_MASK, 0xff)((vh->vh_ph.ph_iot)->write_1((vh->vh_ioh_vga), (0x06 ), (0xff))); | |||
1214 | vga_raw_write(vh, VGA_DAC_READ, 0x00)((vh->vh_ph.ph_iot)->write_1((vh->vh_ioh_vga), (0x07 ), (0x00))); | |||
1215 | for (i = 0; i < 3 * 256; i++) | |||
1216 | *palette++ = vga_raw_read(vh, VGA_DAC_DATA)((vh->vh_ph.ph_iot)->read_1((vh->vh_ioh_vga), (0x09) )); | |||
1217 | } | |||
1218 | ||||
1219 | void | |||
1220 | vga_restore_palette(struct vga_config *vc) | |||
1221 | { | |||
1222 | struct vga_handle *vh = &vc->hdl; | |||
1223 | uint i; | |||
1224 | uint8_t *palette = vc->vc_palette; | |||
1225 | ||||
1226 | if (vh->vh_mono) | |||
1227 | return; | |||
1228 | ||||
1229 | vga_raw_write(vh, VGA_DAC_MASK, 0xff)((vh->vh_ph.ph_iot)->write_1((vh->vh_ioh_vga), (0x06 ), (0xff))); | |||
1230 | vga_raw_write(vh, VGA_DAC_WRITE, 0x00)((vh->vh_ph.ph_iot)->write_1((vh->vh_ioh_vga), (0x08 ), (0x00))); | |||
1231 | for (i = 0; i < 3 * 256; i++) | |||
1232 | vga_raw_write(vh, VGA_DAC_DATA, *palette++)((vh->vh_ph.ph_iot)->write_1((vh->vh_ioh_vga), (0x09 ), (*palette++))); | |||
1233 | } | |||
1234 | ||||
1235 | void | |||
1236 | vga_restore_fonts(struct vga_config *vc) | |||
1237 | { | |||
1238 | int slot; | |||
1239 | struct vgafont *f; | |||
1240 | ||||
1241 | for (slot = 0; slot < VGA_MAXFONT8; slot++) { | |||
1242 | f = vc->vc_fonts[slot]; | |||
1243 | if (f == NULL((void *)0) || f->fontdata == NULL((void *)0)) | |||
1244 | continue; | |||
1245 | ||||
1246 | vga_loadchars(&vc->hdl, slot, 0, 256, f->height, f->fontdata); | |||
1247 | } | |||
1248 | } | |||
1249 | ||||
1250 | #ifdef __alpha__ | |||
1251 | void | |||
1252 | vga_pick_monitor_type(struct vga_config *vc) | |||
1253 | { | |||
1254 | struct vga_handle *vh = &vc->hdl; | |||
1255 | ||||
1256 | /* | |||
1257 | * The Tadpole Alphabook1 uses a 800x600 flat panel in text mode, | |||
1258 | * causing the display console to really be 100x37 instead of the | |||
1259 | * usual 80x25. | |||
1260 | * We attempt to detect this here by checking the CRTC registers. | |||
1261 | */ | |||
1262 | unsigned int hend, oflow, vend; | |||
1263 | unsigned int width, height; | |||
1264 | ||||
1265 | hend = vga_6845_read(vh, hdisple)_pcdisplay_6845_read(&(vh)->vh_ph, __builtin_offsetof( struct reg_mc6845, hdisple)); | |||
1266 | oflow = vga_6845_read(vh, overfll)_pcdisplay_6845_read(&(vh)->vh_ph, __builtin_offsetof( struct reg_mc6845, overfll)); | |||
1267 | vend = vga_6845_read(vh, vde)_pcdisplay_6845_read(&(vh)->vh_ph, __builtin_offsetof( struct reg_mc6845, vde)); | |||
1268 | if (oflow & 0x02) | |||
1269 | vend |= 0x100; | |||
1270 | if (oflow & 0x40) | |||
1271 | vend |= 0x200; | |||
1272 | ||||
1273 | width = hend + 1; | |||
1274 | height = (vend + 1) / 16; | |||
1275 | ||||
1276 | /* check that the values sound plausible */ | |||
1277 | if ((width > 80 && width <= 128) && (height > 25 && height <= 50)) { | |||
1278 | snprintf(vc->custom_scr.name, sizeof(vc->custom_scr.name), | |||
1279 | "%ux%u", width, height); | |||
1280 | vc->custom_scr.ncols = width; | |||
1281 | vc->custom_scr.nrows = height; | |||
1282 | vc->custom_scr.textops = &vga_emulops; | |||
1283 | vc->custom_scr.fontwidth = 8; | |||
1284 | vc->custom_scr.fontheight = 16; | |||
1285 | vc->custom_scr.capabilities = | |||
1286 | WSSCREEN_WSCOLORS1 | WSSCREEN_HILIT4 | WSSCREEN_BLINK8; | |||
1287 | vc->custom_scrlist[0] = &vc->custom_scr; | |||
1288 | vc->custom_list.nscreens = 1; | |||
1289 | vc->custom_list.screens = | |||
1290 | (const struct wsscreen_descr **)vc->custom_scrlist; | |||
1291 | } | |||
1292 | } | |||
1293 | #endif | |||
1294 | ||||
1295 | struct cfdriver vga_cd = { | |||
1296 | NULL((void *)0), "vga", DV_DULL | |||
1297 | }; |