1 | /****************************************************************************** |
---|
2 | * vga.c |
---|
3 | * |
---|
4 | * VGA support routines. |
---|
5 | */ |
---|
6 | |
---|
7 | #include <xen/config.h> |
---|
8 | #include <xen/compile.h> |
---|
9 | #include <xen/init.h> |
---|
10 | #include <xen/lib.h> |
---|
11 | #include <xen/mm.h> |
---|
12 | #include <xen/errno.h> |
---|
13 | #include <xen/event.h> |
---|
14 | #include <xen/spinlock.h> |
---|
15 | #include <xen/console.h> |
---|
16 | #include <xen/vga.h> |
---|
17 | #include <asm/io.h> |
---|
18 | #include "font.h" |
---|
19 | |
---|
20 | /* Some of the code below is taken from SVGAlib. The original, |
---|
21 | unmodified copyright notice for that code is below. */ |
---|
22 | /* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ |
---|
23 | /* */ |
---|
24 | /* This library is free software; you can redistribute it and/or */ |
---|
25 | /* modify it without any restrictions. This library is distributed */ |
---|
26 | /* in the hope that it will be useful, but without any warranty. */ |
---|
27 | |
---|
28 | /* Multi-chipset support Copyright 1993 Harm Hanemaayer */ |
---|
29 | /* partially copyrighted (C) 1993 by Hartmut Schirmer */ |
---|
30 | |
---|
31 | /* VGA data register ports */ |
---|
32 | #define VGA_CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */ |
---|
33 | #define VGA_CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */ |
---|
34 | #define VGA_ATT_R 0x3C1 /* Attribute Controller Data Read Register */ |
---|
35 | #define VGA_ATT_W 0x3C0 /* Attribute Controller Data Write Register */ |
---|
36 | #define VGA_GFX_D 0x3CF /* Graphics Controller Data Register */ |
---|
37 | #define VGA_SEQ_D 0x3C5 /* Sequencer Data Register */ |
---|
38 | #define VGA_MIS_R 0x3CC /* Misc Output Read Register */ |
---|
39 | #define VGA_MIS_W 0x3C2 /* Misc Output Write Register */ |
---|
40 | #define VGA_FTC_R 0x3CA /* Feature Control Read Register */ |
---|
41 | #define VGA_IS1_RC 0x3DA /* Input Status Register 1 - color emulation */ |
---|
42 | #define VGA_IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */ |
---|
43 | #define VGA_PEL_D 0x3C9 /* PEL Data Register */ |
---|
44 | #define VGA_PEL_MSK 0x3C6 /* PEL mask register */ |
---|
45 | |
---|
46 | /* EGA-specific registers */ |
---|
47 | #define EGA_GFX_E0 0x3CC /* Graphics enable processor 0 */ |
---|
48 | #define EGA_GFX_E1 0x3CA /* Graphics enable processor 1 */ |
---|
49 | |
---|
50 | /* VGA index register ports */ |
---|
51 | #define VGA_CRT_IC 0x3D4 /* CRT Controller Index - color emulation */ |
---|
52 | #define VGA_CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */ |
---|
53 | #define VGA_ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ |
---|
54 | #define VGA_GFX_I 0x3CE /* Graphics Controller Index */ |
---|
55 | #define VGA_SEQ_I 0x3C4 /* Sequencer Index */ |
---|
56 | #define VGA_PEL_IW 0x3C8 /* PEL Write Index */ |
---|
57 | #define VGA_PEL_IR 0x3C7 /* PEL Read Index */ |
---|
58 | |
---|
59 | /* standard VGA indexes max counts */ |
---|
60 | #define VGA_CRT_C 0x19 /* Number of CRT Controller Registers */ |
---|
61 | #define VGA_ATT_C 0x15 /* Number of Attribute Controller Registers */ |
---|
62 | #define VGA_GFX_C 0x09 /* Number of Graphics Controller Registers */ |
---|
63 | #define VGA_SEQ_C 0x05 /* Number of Sequencer Registers */ |
---|
64 | #define VGA_MIS_C 0x01 /* Number of Misc Output Register */ |
---|
65 | |
---|
66 | /* VGA misc register bit masks */ |
---|
67 | #define VGA_MIS_COLOR 0x01 |
---|
68 | #define VGA_MIS_ENB_MEM_ACCESS 0x02 |
---|
69 | #define VGA_MIS_DCLK_28322_720 0x04 |
---|
70 | #define VGA_MIS_ENB_PLL_LOAD (0x04 | 0x08) |
---|
71 | #define VGA_MIS_SEL_HIGH_PAGE 0x20 |
---|
72 | |
---|
73 | /* VGA CRT controller register indices */ |
---|
74 | #define VGA_CRTC_H_TOTAL 0 |
---|
75 | #define VGA_CRTC_H_DISP 1 |
---|
76 | #define VGA_CRTC_H_BLANK_START 2 |
---|
77 | #define VGA_CRTC_H_BLANK_END 3 |
---|
78 | #define VGA_CRTC_H_SYNC_START 4 |
---|
79 | #define VGA_CRTC_H_SYNC_END 5 |
---|
80 | #define VGA_CRTC_V_TOTAL 6 |
---|
81 | #define VGA_CRTC_OVERFLOW 7 |
---|
82 | #define VGA_CRTC_PRESET_ROW 8 |
---|
83 | #define VGA_CRTC_MAX_SCAN 9 |
---|
84 | #define VGA_CRTC_CURSOR_START 0x0A |
---|
85 | #define VGA_CRTC_CURSOR_END 0x0B |
---|
86 | #define VGA_CRTC_START_HI 0x0C |
---|
87 | #define VGA_CRTC_START_LO 0x0D |
---|
88 | #define VGA_CRTC_CURSOR_HI 0x0E |
---|
89 | #define VGA_CRTC_CURSOR_LO 0x0F |
---|
90 | #define VGA_CRTC_V_SYNC_START 0x10 |
---|
91 | #define VGA_CRTC_V_SYNC_END 0x11 |
---|
92 | #define VGA_CRTC_V_DISP_END 0x12 |
---|
93 | #define VGA_CRTC_OFFSET 0x13 |
---|
94 | #define VGA_CRTC_UNDERLINE 0x14 |
---|
95 | #define VGA_CRTC_V_BLANK_START 0x15 |
---|
96 | #define VGA_CRTC_V_BLANK_END 0x16 |
---|
97 | #define VGA_CRTC_MODE 0x17 |
---|
98 | #define VGA_CRTC_LINE_COMPARE 0x18 |
---|
99 | #define VGA_CRTC_REGS VGA_CRT_C |
---|
100 | |
---|
101 | /* VGA CRT controller bit masks */ |
---|
102 | #define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */ |
---|
103 | #define VGA_CR17_H_V_SIGNALS_ENABLED 0x80 |
---|
104 | |
---|
105 | /* VGA attribute controller register indices */ |
---|
106 | #define VGA_ATC_PALETTE0 0x00 |
---|
107 | #define VGA_ATC_PALETTE1 0x01 |
---|
108 | #define VGA_ATC_PALETTE2 0x02 |
---|
109 | #define VGA_ATC_PALETTE3 0x03 |
---|
110 | #define VGA_ATC_PALETTE4 0x04 |
---|
111 | #define VGA_ATC_PALETTE5 0x05 |
---|
112 | #define VGA_ATC_PALETTE6 0x06 |
---|
113 | #define VGA_ATC_PALETTE7 0x07 |
---|
114 | #define VGA_ATC_PALETTE8 0x08 |
---|
115 | #define VGA_ATC_PALETTE9 0x09 |
---|
116 | #define VGA_ATC_PALETTEA 0x0A |
---|
117 | #define VGA_ATC_PALETTEB 0x0B |
---|
118 | #define VGA_ATC_PALETTEC 0x0C |
---|
119 | #define VGA_ATC_PALETTED 0x0D |
---|
120 | #define VGA_ATC_PALETTEE 0x0E |
---|
121 | #define VGA_ATC_PALETTEF 0x0F |
---|
122 | #define VGA_ATC_MODE 0x10 |
---|
123 | #define VGA_ATC_OVERSCAN 0x11 |
---|
124 | #define VGA_ATC_PLANE_ENABLE 0x12 |
---|
125 | #define VGA_ATC_PEL 0x13 |
---|
126 | #define VGA_ATC_COLOR_PAGE 0x14 |
---|
127 | |
---|
128 | #define VGA_AR_ENABLE_DISPLAY 0x20 |
---|
129 | |
---|
130 | /* VGA sequencer register indices */ |
---|
131 | #define VGA_SEQ_RESET 0x00 |
---|
132 | #define VGA_SEQ_CLOCK_MODE 0x01 |
---|
133 | #define VGA_SEQ_PLANE_WRITE 0x02 |
---|
134 | #define VGA_SEQ_CHARACTER_MAP 0x03 |
---|
135 | #define VGA_SEQ_MEMORY_MODE 0x04 |
---|
136 | |
---|
137 | /* VGA sequencer register bit masks */ |
---|
138 | #define VGA_SR01_CHAR_CLK_8DOTS 0x01 /* bit 0: character clocks 8 dots wide are generated */ |
---|
139 | #define VGA_SR01_SCREEN_OFF 0x20 /* bit 5: Screen is off */ |
---|
140 | #define VGA_SR02_ALL_PLANES 0x0F /* bits 3-0: enable access to all planes */ |
---|
141 | #define VGA_SR04_EXT_MEM 0x02 /* bit 1: allows complete mem access to 256K */ |
---|
142 | #define VGA_SR04_SEQ_MODE 0x04 /* bit 2: directs system to use a sequential addressing mode */ |
---|
143 | #define VGA_SR04_CHN_4M 0x08 /* bit 3: selects modulo 4 addressing for CPU access to display memory */ |
---|
144 | |
---|
145 | /* VGA graphics controller register indices */ |
---|
146 | #define VGA_GFX_SR_VALUE 0x00 |
---|
147 | #define VGA_GFX_SR_ENABLE 0x01 |
---|
148 | #define VGA_GFX_COMPARE_VALUE 0x02 |
---|
149 | #define VGA_GFX_DATA_ROTATE 0x03 |
---|
150 | #define VGA_GFX_PLANE_READ 0x04 |
---|
151 | #define VGA_GFX_MODE 0x05 |
---|
152 | #define VGA_GFX_MISC 0x06 |
---|
153 | #define VGA_GFX_COMPARE_MASK 0x07 |
---|
154 | #define VGA_GFX_BIT_MASK 0x08 |
---|
155 | |
---|
156 | /* VGA graphics controller bit masks */ |
---|
157 | #define VGA_GR06_GRAPHICS_MODE 0x01 |
---|
158 | |
---|
159 | /* macro for composing an 8-bit VGA register index and value |
---|
160 | * into a single 16-bit quantity */ |
---|
161 | #define VGA_OUT16VAL(v, r) (((v) << 8) | (r)) |
---|
162 | |
---|
163 | #define vgabase 0 /* use in/out port-access macros */ |
---|
164 | #define VGA_OUTW_WRITE /* can use outw instead of 2xoutb */ |
---|
165 | |
---|
166 | /* |
---|
167 | * generic VGA port read/write |
---|
168 | */ |
---|
169 | |
---|
170 | static inline uint8_t vga_io_r(uint16_t port) |
---|
171 | { |
---|
172 | return inb(port); |
---|
173 | } |
---|
174 | |
---|
175 | static inline void vga_io_w(uint16_t port, uint8_t val) |
---|
176 | { |
---|
177 | outb(val, port); |
---|
178 | } |
---|
179 | |
---|
180 | static inline void vga_io_w_fast(uint16_t port, uint8_t reg, uint8_t val) |
---|
181 | { |
---|
182 | outw(VGA_OUT16VAL(val, reg), port); |
---|
183 | } |
---|
184 | |
---|
185 | static inline uint8_t vga_mm_r(void __iomem *regbase, uint16_t port) |
---|
186 | { |
---|
187 | return readb((char *)regbase + port); |
---|
188 | } |
---|
189 | |
---|
190 | static inline void vga_mm_w(void __iomem *regbase, uint16_t port, uint8_t val) |
---|
191 | { |
---|
192 | writeb(val, (char *)regbase + port); |
---|
193 | } |
---|
194 | |
---|
195 | static inline void vga_mm_w_fast(void __iomem *regbase, uint16_t port, uint8_t reg, uint8_t val) |
---|
196 | { |
---|
197 | writew(VGA_OUT16VAL(val, reg), (char *)regbase + port); |
---|
198 | } |
---|
199 | |
---|
200 | static inline uint8_t vga_r(void __iomem *regbase, uint16_t port) |
---|
201 | { |
---|
202 | if (regbase) |
---|
203 | return vga_mm_r(regbase, port); |
---|
204 | else |
---|
205 | return vga_io_r(port); |
---|
206 | } |
---|
207 | |
---|
208 | static inline void vga_w(void __iomem *regbase, uint16_t port, uint8_t val) |
---|
209 | { |
---|
210 | if (regbase) |
---|
211 | vga_mm_w(regbase, port, val); |
---|
212 | else |
---|
213 | vga_io_w(port, val); |
---|
214 | } |
---|
215 | |
---|
216 | |
---|
217 | static inline void vga_w_fast(void __iomem *regbase, uint16_t port, uint8_t reg, uint8_t val) |
---|
218 | { |
---|
219 | if (regbase) |
---|
220 | vga_mm_w_fast(regbase, port, reg, val); |
---|
221 | else |
---|
222 | vga_io_w_fast(port, reg, val); |
---|
223 | } |
---|
224 | |
---|
225 | |
---|
226 | /* |
---|
227 | * VGA CRTC register read/write |
---|
228 | */ |
---|
229 | |
---|
230 | static inline uint8_t vga_rcrt(void __iomem *regbase, uint8_t reg) |
---|
231 | { |
---|
232 | vga_w(regbase, VGA_CRT_IC, reg); |
---|
233 | return vga_r(regbase, VGA_CRT_DC); |
---|
234 | } |
---|
235 | |
---|
236 | static inline void vga_wcrt(void __iomem *regbase, uint8_t reg, uint8_t val) |
---|
237 | { |
---|
238 | #ifdef VGA_OUTW_WRITE |
---|
239 | vga_w_fast(regbase, VGA_CRT_IC, reg, val); |
---|
240 | #else |
---|
241 | vga_w(regbase, VGA_CRT_IC, reg); |
---|
242 | vga_w(regbase, VGA_CRT_DC, val); |
---|
243 | #endif /* VGA_OUTW_WRITE */ |
---|
244 | } |
---|
245 | |
---|
246 | /* |
---|
247 | * VGA sequencer register read/write |
---|
248 | */ |
---|
249 | |
---|
250 | static inline uint8_t vga_rseq(void __iomem *regbase, uint8_t reg) |
---|
251 | { |
---|
252 | vga_w(regbase, VGA_SEQ_I, reg); |
---|
253 | return vga_r(regbase, VGA_SEQ_D); |
---|
254 | } |
---|
255 | |
---|
256 | static inline void vga_wseq(void __iomem *regbase, uint8_t reg, uint8_t val) |
---|
257 | { |
---|
258 | #ifdef VGA_OUTW_WRITE |
---|
259 | vga_w_fast(regbase, VGA_SEQ_I, reg, val); |
---|
260 | #else |
---|
261 | vga_w(regbase, VGA_SEQ_I, reg); |
---|
262 | vga_w(regbase, VGA_SEQ_D, val); |
---|
263 | #endif /* VGA_OUTW_WRITE */ |
---|
264 | } |
---|
265 | |
---|
266 | /* |
---|
267 | * VGA graphics controller register read/write |
---|
268 | */ |
---|
269 | |
---|
270 | static inline uint8_t vga_rgfx(void __iomem *regbase, uint8_t reg) |
---|
271 | { |
---|
272 | vga_w(regbase, VGA_GFX_I, reg); |
---|
273 | return vga_r(regbase, VGA_GFX_D); |
---|
274 | } |
---|
275 | |
---|
276 | static inline void vga_wgfx(void __iomem *regbase, uint8_t reg, uint8_t val) |
---|
277 | { |
---|
278 | #ifdef VGA_OUTW_WRITE |
---|
279 | vga_w_fast(regbase, VGA_GFX_I, reg, val); |
---|
280 | #else |
---|
281 | vga_w(regbase, VGA_GFX_I, reg); |
---|
282 | vga_w(regbase, VGA_GFX_D, val); |
---|
283 | #endif /* VGA_OUTW_WRITE */ |
---|
284 | } |
---|
285 | |
---|
286 | /* |
---|
287 | * VGA attribute controller register read/write |
---|
288 | */ |
---|
289 | |
---|
290 | static inline uint8_t vga_rattr(void __iomem *regbase, uint8_t reg) |
---|
291 | { |
---|
292 | vga_w(regbase, VGA_ATT_IW, reg); |
---|
293 | return vga_r(regbase, VGA_ATT_R); |
---|
294 | } |
---|
295 | |
---|
296 | static inline void vga_wattr(void __iomem *regbase, uint8_t reg, uint8_t val) |
---|
297 | { |
---|
298 | vga_w(regbase, VGA_ATT_IW, reg); |
---|
299 | vga_w(regbase, VGA_ATT_W, val); |
---|
300 | } |
---|
301 | |
---|
302 | static int detect_video(void *video_base) |
---|
303 | { |
---|
304 | volatile u16 *p = (volatile u16 *)video_base; |
---|
305 | u16 saved1 = p[0], saved2 = p[1]; |
---|
306 | int video_found = 1; |
---|
307 | |
---|
308 | p[0] = 0xAA55; |
---|
309 | p[1] = 0x55AA; |
---|
310 | if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) ) |
---|
311 | video_found = 0; |
---|
312 | |
---|
313 | p[0] = 0x55AA; |
---|
314 | p[1] = 0xAA55; |
---|
315 | if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) ) |
---|
316 | video_found = 0; |
---|
317 | |
---|
318 | p[0] = saved1; |
---|
319 | p[1] = saved2; |
---|
320 | |
---|
321 | return video_found; |
---|
322 | } |
---|
323 | |
---|
324 | /* This is actually code from vgaHWRestore in an old version of XFree86 :-) */ |
---|
325 | static void *setup_vga(void) |
---|
326 | { |
---|
327 | /* The following VGA state was saved from a chip in text mode 3. */ |
---|
328 | static unsigned char regs[] = { |
---|
329 | /* Sequencer registers */ |
---|
330 | 0x03, 0x00, 0x03, 0x00, 0x02, |
---|
331 | /* CRTC registers */ |
---|
332 | 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20, |
---|
333 | 0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, |
---|
334 | 0xb9, 0xa3, 0xff, |
---|
335 | /* Graphic registers */ |
---|
336 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff, |
---|
337 | /* Attribute registers */ |
---|
338 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a, |
---|
339 | 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00 |
---|
340 | }; |
---|
341 | |
---|
342 | char *video; |
---|
343 | int i, j; |
---|
344 | |
---|
345 | if ( memory_is_conventional_ram(0xB8000) ) |
---|
346 | goto no_vga; |
---|
347 | |
---|
348 | inb(VGA_IS1_RC); |
---|
349 | outb(0x00, VGA_ATT_IW); |
---|
350 | |
---|
351 | for ( i = j = 0; i < 5; i++ ) |
---|
352 | vga_wseq(vgabase, i, regs[j++]); |
---|
353 | |
---|
354 | /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */ |
---|
355 | vga_wcrt(vgabase, 17, regs[5+17] & 0x7F); |
---|
356 | |
---|
357 | for ( i = 0; i < 25; i++ ) |
---|
358 | vga_wcrt(vgabase, i, regs[j++]); |
---|
359 | |
---|
360 | for ( i = 0; i < 9; i++ ) |
---|
361 | vga_wgfx(vgabase, i, regs[j++]); |
---|
362 | |
---|
363 | inb(VGA_IS1_RC); |
---|
364 | for ( i = 0; i < 21; i++ ) |
---|
365 | vga_wattr(vgabase, i, regs[j++]); |
---|
366 | |
---|
367 | inb(VGA_IS1_RC); |
---|
368 | outb(0x20, VGA_ATT_IW); |
---|
369 | |
---|
370 | video = ioremap(0xB8000, 0x8000); |
---|
371 | |
---|
372 | if ( !detect_video(video) ) |
---|
373 | { |
---|
374 | iounmap(video); |
---|
375 | goto no_vga; |
---|
376 | } |
---|
377 | |
---|
378 | return video; |
---|
379 | |
---|
380 | no_vga: |
---|
381 | printk("No VGA adaptor detected!\n"); |
---|
382 | return NULL; |
---|
383 | } |
---|
384 | |
---|
385 | static int vga_set_scanlines(unsigned scanlines) |
---|
386 | { |
---|
387 | unsigned vtot, ovr, vss, vbs; |
---|
388 | uint8_t vse, vbe, misc = 0; |
---|
389 | |
---|
390 | switch (scanlines) { |
---|
391 | case 43*8: |
---|
392 | vtot = 0x1bf; |
---|
393 | vss = 0x183; |
---|
394 | vse = 0x05; |
---|
395 | vbs = 0x163; |
---|
396 | vbe = 0xba; |
---|
397 | break; |
---|
398 | case 25*16: |
---|
399 | case 28*14: |
---|
400 | vtot = 0x1bf; |
---|
401 | vss = 0x19c; |
---|
402 | vse = 0x0e; |
---|
403 | vbs = 0x196; |
---|
404 | vbe = 0xb9; |
---|
405 | break; |
---|
406 | case 30*16: |
---|
407 | case 34*14: |
---|
408 | vtot = 0x20b; |
---|
409 | vss = 0x1ea; |
---|
410 | vse = 0x0c; |
---|
411 | vbs = 0x1e7; |
---|
412 | vbe = 0x04; |
---|
413 | /* Preserve clock select bits and color bit, set correct sync polarity. */ |
---|
414 | misc = (inb(VGA_MIS_R) & 0x0d) | 0xe2; |
---|
415 | break; |
---|
416 | default: |
---|
417 | return -ENOSYS; |
---|
418 | } |
---|
419 | |
---|
420 | ovr = vga_rcrt(vgabase, VGA_CRTC_OVERFLOW); |
---|
421 | if(vga_rcrt(vgabase, VGA_CRTC_V_DISP_END) + ((ovr & 0x02) << 7) + ((ovr & 0x40) << 3) == scanlines - 1) |
---|
422 | return 0; |
---|
423 | |
---|
424 | ovr = (ovr & 0x10) |
---|
425 | | ((vtot >> 8) & 0x01) |
---|
426 | | ((vtot >> 4) & 0x20) |
---|
427 | | (((scanlines - 1) >> 7) & 0x02) |
---|
428 | | (((scanlines - 1) >> 3) & 0x40) |
---|
429 | | ((vss >> 6) & 0x04) |
---|
430 | | ((vss >> 2) & 0x80) |
---|
431 | | ((vbs >> 5) & 0x08); |
---|
432 | vse |= vga_rcrt(vgabase, VGA_CRTC_V_SYNC_END) & 0x70; |
---|
433 | |
---|
434 | vga_wcrt(vgabase, VGA_CRTC_V_SYNC_END, vse & 0x7f); /* Vertical sync end (also unlocks CR0-7) */ |
---|
435 | vga_wcrt(vgabase, VGA_CRTC_V_TOTAL, (uint8_t)vtot); /* Vertical total */ |
---|
436 | vga_wcrt(vgabase, VGA_CRTC_OVERFLOW, (uint8_t)ovr); /* Overflow */ |
---|
437 | vga_wcrt(vgabase, VGA_CRTC_V_SYNC_START, (uint8_t)vss); /* Vertical sync start */ |
---|
438 | vga_wcrt(vgabase, VGA_CRTC_V_SYNC_END, vse | 0x80); /* Vertical sync end (also locks CR0-7) */ |
---|
439 | vga_wcrt(vgabase, VGA_CRTC_V_DISP_END, (uint8_t)(scanlines - 1)); /* Vertical display end */ |
---|
440 | vga_wcrt(vgabase, VGA_CRTC_V_BLANK_START, (uint8_t)vbs); /* Vertical blank start */ |
---|
441 | vga_wcrt(vgabase, VGA_CRTC_V_BLANK_END, vbe); /* Vertical blank end */ |
---|
442 | |
---|
443 | if (misc) |
---|
444 | outb(misc, VGA_MIS_W); /* Misc output register */ |
---|
445 | |
---|
446 | return 0; |
---|
447 | } |
---|
448 | |
---|
449 | #define FONT_COUNT_MAX 256 |
---|
450 | #define FONT_HEIGHT_MAX 32 |
---|
451 | #define CHAR_MAP_SIZE (FONT_COUNT_MAX * FONT_HEIGHT_MAX) |
---|
452 | |
---|
453 | /* |
---|
454 | * We use font slot 0 because ATI cards do not honour changes to the |
---|
455 | * character map select register. The fontslot parameter can be used to |
---|
456 | * choose a non-default slot if the video card supports it and you wish to |
---|
457 | * preserve the BIOS-initialised font data. |
---|
458 | */ |
---|
459 | static unsigned font_slot = 0; |
---|
460 | integer_param("fontslot", font_slot); |
---|
461 | |
---|
462 | static int vga_load_font(const struct font_desc *font, unsigned rows) |
---|
463 | { |
---|
464 | unsigned fontheight = font ? font->height : 16; |
---|
465 | uint8_t fsr = vga_rcrt(vgabase, VGA_CRTC_MAX_SCAN); /* Font size register */ |
---|
466 | int ret; |
---|
467 | |
---|
468 | if (font_slot > 3 || (!font_slot && !font)) |
---|
469 | return -ENOSYS; |
---|
470 | |
---|
471 | if (font |
---|
472 | && (font->count > FONT_COUNT_MAX |
---|
473 | || fontheight > FONT_HEIGHT_MAX |
---|
474 | || font->width != 8)) |
---|
475 | return -EINVAL; |
---|
476 | |
---|
477 | ret = vga_set_scanlines(rows * fontheight); |
---|
478 | if (ret < 0) |
---|
479 | return ret; |
---|
480 | |
---|
481 | if ((fsr & 0x1f) == fontheight - 1) |
---|
482 | return 0; |
---|
483 | |
---|
484 | /* First, the Sequencer */ |
---|
485 | vga_wseq(vgabase, VGA_SEQ_RESET, 0x1); |
---|
486 | /* CPU writes only to map 2 */ |
---|
487 | vga_wseq(vgabase, VGA_SEQ_PLANE_WRITE, 0x04); |
---|
488 | /* Sequential addressing */ |
---|
489 | vga_wseq(vgabase, VGA_SEQ_MEMORY_MODE, 0x07); |
---|
490 | /* Clear synchronous reset */ |
---|
491 | vga_wseq(vgabase, VGA_SEQ_RESET, 0x03); |
---|
492 | |
---|
493 | /* Now, the graphics controller, select map 2 */ |
---|
494 | vga_wgfx(vgabase, VGA_GFX_PLANE_READ, 0x02); |
---|
495 | /* disable odd-even addressing */ |
---|
496 | vga_wgfx(vgabase, VGA_GFX_MODE, 0x00); |
---|
497 | /* map start at A000:0000 */ |
---|
498 | vga_wgfx(vgabase, VGA_GFX_MISC, 0x00); |
---|
499 | |
---|
500 | if ( font ) |
---|
501 | { |
---|
502 | unsigned i, j; |
---|
503 | const uint8_t *data = font->data; |
---|
504 | uint8_t *map; |
---|
505 | |
---|
506 | map = ioremap(0xA0000 + font_slot*2*CHAR_MAP_SIZE, CHAR_MAP_SIZE); |
---|
507 | |
---|
508 | for ( i = j = 0; i < CHAR_MAP_SIZE; ) |
---|
509 | { |
---|
510 | writeb(j < font->count * fontheight ? data[j++] : 0, map + i++); |
---|
511 | if ( !(j % fontheight) ) |
---|
512 | while ( i & (FONT_HEIGHT_MAX - 1) ) |
---|
513 | writeb(0, map + i++); |
---|
514 | } |
---|
515 | |
---|
516 | iounmap(map); |
---|
517 | } |
---|
518 | |
---|
519 | /* First, the sequencer, Synchronous reset */ |
---|
520 | vga_wseq(vgabase, VGA_SEQ_RESET, 0x01); |
---|
521 | /* CPU writes to maps 0 and 1 */ |
---|
522 | vga_wseq(vgabase, VGA_SEQ_PLANE_WRITE, 0x03); |
---|
523 | /* odd-even addressing */ |
---|
524 | vga_wseq(vgabase, VGA_SEQ_MEMORY_MODE, 0x03); |
---|
525 | /* Character Map Select: The default font is kept in slot 0. */ |
---|
526 | vga_wseq(vgabase, VGA_SEQ_CHARACTER_MAP, |
---|
527 | font ? font_slot | (font_slot << 2) : 0x00); |
---|
528 | /* clear synchronous reset */ |
---|
529 | vga_wseq(vgabase, VGA_SEQ_RESET, 0x03); |
---|
530 | |
---|
531 | /* Now, the graphics controller, select map 0 for CPU */ |
---|
532 | vga_wgfx(vgabase, VGA_GFX_PLANE_READ, 0x00); |
---|
533 | /* enable even-odd addressing */ |
---|
534 | vga_wgfx(vgabase, VGA_GFX_MODE, 0x10); |
---|
535 | /* map starts at b800:0 */ |
---|
536 | vga_wgfx(vgabase, VGA_GFX_MISC, 0x0e); |
---|
537 | |
---|
538 | /* Font size register */ |
---|
539 | fsr = (fsr & 0xe0) + (fontheight - 1); |
---|
540 | vga_wcrt(vgabase, VGA_CRTC_MAX_SCAN, fsr); |
---|
541 | |
---|
542 | /* Cursor shape registers */ |
---|
543 | fsr = vga_rcrt(vgabase, VGA_CRTC_CURSOR_END) & 0xe0; |
---|
544 | fsr |= fontheight - fontheight / 6; |
---|
545 | vga_wcrt(vgabase, VGA_CRTC_CURSOR_END, fsr); |
---|
546 | fsr = vga_rcrt(vgabase, VGA_CRTC_CURSOR_START) & 0xe0; |
---|
547 | fsr |= (fsr & 0x1f) - 1; |
---|
548 | vga_wcrt(vgabase, VGA_CRTC_CURSOR_START, fsr); |
---|
549 | |
---|
550 | return 0; |
---|
551 | } |
---|
552 | |
---|
553 | |
---|
554 | /* |
---|
555 | * HIGH-LEVEL INITIALISATION AND TEXT OUTPUT. |
---|
556 | */ |
---|
557 | |
---|
558 | static int vgacon_enabled = 0; |
---|
559 | static int vgacon_keep = 0; |
---|
560 | static int vgacon_lines = 50; |
---|
561 | static const struct font_desc *font; |
---|
562 | |
---|
563 | static int xpos, ypos; |
---|
564 | static unsigned char *video; |
---|
565 | |
---|
566 | /* vga: comma-separated options. */ |
---|
567 | static char opt_vga[30] = ""; |
---|
568 | string_param("vga", opt_vga); |
---|
569 | |
---|
570 | /* VGA text-mode definitions. */ |
---|
571 | #define COLUMNS 80 |
---|
572 | #define LINES vgacon_lines |
---|
573 | #define ATTRIBUTE 7 |
---|
574 | #define VIDEO_SIZE (COLUMNS * LINES * 2) |
---|
575 | |
---|
576 | void vga_init(void) |
---|
577 | { |
---|
578 | char *p; |
---|
579 | |
---|
580 | for ( p = opt_vga; p != NULL; p = strchr(p, ',') ) |
---|
581 | { |
---|
582 | if ( *p == ',' ) |
---|
583 | p++; |
---|
584 | if ( strncmp(p, "keep", 4) == 0 ) |
---|
585 | vgacon_keep = 1; |
---|
586 | else if ( strncmp(p, "text-80x", 8) == 0 ) |
---|
587 | vgacon_lines = simple_strtoul(p + 8, NULL, 10); |
---|
588 | } |
---|
589 | |
---|
590 | video = setup_vga(); |
---|
591 | if ( !video ) |
---|
592 | return; |
---|
593 | |
---|
594 | switch ( vgacon_lines ) |
---|
595 | { |
---|
596 | case 25: |
---|
597 | case 30: |
---|
598 | font = &font_vga_8x16; |
---|
599 | break; |
---|
600 | case 28: |
---|
601 | case 34: |
---|
602 | font = &font_vga_8x14; |
---|
603 | break; |
---|
604 | case 43: |
---|
605 | case 50: |
---|
606 | case 60: |
---|
607 | font = &font_vga_8x8; |
---|
608 | break; |
---|
609 | } |
---|
610 | |
---|
611 | if ( (font == NULL) || (vga_load_font(font, vgacon_lines) < 0) ) |
---|
612 | { |
---|
613 | vgacon_lines = 25; |
---|
614 | font = NULL; |
---|
615 | } |
---|
616 | |
---|
617 | /* Clear the screen. */ |
---|
618 | memset(video, 0, VIDEO_SIZE); |
---|
619 | xpos = ypos = 0; |
---|
620 | |
---|
621 | /* Disable cursor. */ |
---|
622 | vga_wcrt(vgabase, VGA_CRTC_CURSOR_START, 0x20); |
---|
623 | |
---|
624 | vgacon_enabled = 1; |
---|
625 | } |
---|
626 | |
---|
627 | void vga_endboot(void) |
---|
628 | { |
---|
629 | if ( !vgacon_enabled ) |
---|
630 | return; |
---|
631 | |
---|
632 | if ( !vgacon_keep ) |
---|
633 | vgacon_enabled = 0; |
---|
634 | |
---|
635 | printk("Xen is %s VGA console.\n", |
---|
636 | vgacon_keep ? "keeping" : "relinquishing"); |
---|
637 | } |
---|
638 | |
---|
639 | |
---|
640 | static void put_newline(void) |
---|
641 | { |
---|
642 | xpos = 0; |
---|
643 | ypos++; |
---|
644 | |
---|
645 | if ( ypos >= LINES ) |
---|
646 | { |
---|
647 | ypos = LINES-1; |
---|
648 | memmove((char*)video, |
---|
649 | (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS); |
---|
650 | memset((char*)video + (LINES-1)*2*COLUMNS, 0, 2*COLUMNS); |
---|
651 | } |
---|
652 | } |
---|
653 | |
---|
654 | void vga_putchar(int c) |
---|
655 | { |
---|
656 | if ( !vgacon_enabled ) |
---|
657 | return; |
---|
658 | |
---|
659 | if ( c == '\n' ) |
---|
660 | { |
---|
661 | put_newline(); |
---|
662 | } |
---|
663 | else |
---|
664 | { |
---|
665 | if ( xpos >= COLUMNS ) |
---|
666 | put_newline(); |
---|
667 | video[(xpos + ypos * COLUMNS) * 2] = c & 0xFF; |
---|
668 | video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE; |
---|
669 | ++xpos; |
---|
670 | } |
---|
671 | } |
---|
672 | |
---|
673 | int fill_console_start_info(struct dom0_vga_console_info *ci) |
---|
674 | { |
---|
675 | memset(ci, 0, sizeof(*ci)); |
---|
676 | |
---|
677 | if ( !vgacon_enabled ) |
---|
678 | return 0; |
---|
679 | |
---|
680 | ci->video_type = XEN_VGATYPE_TEXT_MODE_3; |
---|
681 | ci->u.text_mode_3.rows = LINES; |
---|
682 | ci->u.text_mode_3.columns = COLUMNS; |
---|
683 | ci->u.text_mode_3.cursor_x = 0; |
---|
684 | ci->u.text_mode_3.cursor_y = LINES - 1; |
---|
685 | ci->u.text_mode_3.font_height = font ? font->height : 16; |
---|
686 | |
---|
687 | return 1; |
---|
688 | } |
---|